about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-11-24 23:06:55 -0800
committerKartik Agaram <vc@akkartik.com>2018-11-24 23:06:55 -0800
commit732cf4e7cc05f00473663855271ec9b6a07d0196 (patch)
tree103cc5913d7b482342a1ec28e251523378ddddc8 /subx
parenta8f47b4a640375af3c949b0347edadf12a8ff579 (diff)
downloadmu-732cf4e7cc05f00473663855271ec9b6a07d0196.tar.gz
4773 - done with crenshaw chapter 2-1
In the process I had to fix a couple more bugs in support for disp16 instructions.
Diffstat (limited to 'subx')
-rw-r--r--subx/018jump_disp16.cc12
-rw-r--r--subx/020syscalls.cc1
-rw-r--r--subx/035labels.cc2
-rwxr-xr-xsubx/apps/crenshaw2-1bin6835 -> 7149 bytes
-rw-r--r--subx/apps/crenshaw2-1.subx128
5 files changed, 128 insertions, 15 deletions
diff --git a/subx/018jump_disp16.cc b/subx/018jump_disp16.cc
index c22fbce4..38ac82ac 100644
--- a/subx/018jump_disp16.cc
+++ b/subx/018jump_disp16.cc
@@ -49,7 +49,7 @@ put_new(Name_0f, "84", "jump disp16 bytes away if equal, if ZF is set (jcc/jz/je
 
 :(before "End Two-Byte Opcodes Starting With 0f")
 case 0x84: {  // jump rel16 if ZF
-  const int8_t offset = imm16();
+  const int16_t offset = imm16();
   if (ZF) {
     trace(90, "run") << "jump " << NUM(offset) << end();
     EIP += offset;
@@ -88,7 +88,7 @@ put_new(Name_0f, "85", "jump disp16 bytes away if not equal, if ZF is not set (j
 
 :(before "End Two-Byte Opcodes Starting With 0f")
 case 0x85: {  // jump rel16 unless ZF
-  const int8_t offset = imm16();
+  const int16_t offset = imm16();
   if (!ZF) {
     trace(90, "run") << "jump " << NUM(offset) << end();
     EIP += offset;
@@ -129,7 +129,7 @@ put_new(Name_0f, "8f", "jump disp16 bytes away if greater, if ZF is unset and SF
 
 :(before "End Two-Byte Opcodes Starting With 0f")
 case 0x8f: {  // jump rel16 if !SF and !ZF
-  const int8_t offset = imm16();
+  const int16_t offset = imm16();
   if (!ZF && SF == OF) {
     trace(90, "run") << "jump " << NUM(offset) << end();
     EIP += offset;
@@ -171,7 +171,7 @@ put_new(Name_0f, "8d", "jump disp16 bytes away if greater or equal, if SF == OF
 
 :(before "End Two-Byte Opcodes Starting With 0f")
 case 0x8d: {  // jump rel16 if !SF
-  const int8_t offset = imm16();
+  const int16_t offset = imm16();
   if (SF == OF) {
     trace(90, "run") << "jump " << NUM(offset) << end();
     EIP += offset;
@@ -213,7 +213,7 @@ put_new(Name_0f, "8c", "jump disp16 bytes away if lesser, if SF != OF (jcc/jl/jn
 
 :(before "End Two-Byte Opcodes Starting With 0f")
 case 0x8c: {  // jump rel16 if SF and !ZF
-  const int8_t offset = imm16();
+  const int16_t offset = imm16();
   if (SF != OF) {
     trace(90, "run") << "jump " << NUM(offset) << end();
     EIP += offset;
@@ -270,7 +270,7 @@ put_new(Name_0f, "8e", "jump disp16 bytes away if lesser or equal, if ZF is set
 
 :(before "End Two-Byte Opcodes Starting With 0f")
 case 0x8e: {  // jump rel16 if SF or ZF
-  const int8_t offset = imm16();
+  const int16_t offset = imm16();
   if (ZF || SF != OF) {
     trace(90, "run") << "jump " << NUM(offset) << end();
     EIP += offset;
diff --git a/subx/020syscalls.cc b/subx/020syscalls.cc
index e45fae9c..675fb526 100644
--- a/subx/020syscalls.cc
+++ b/subx/020syscalls.cc
@@ -22,7 +22,6 @@ void process_int80() {
     break;
   case 3:
     trace(91, "run") << "read: " << Reg[EBX].u << ' ' << Reg[ECX].u << ' ' << Reg[EDX].u << end();
-    trace(91, "run") << Reg[ECX].u << " => " << mem_addr_string(Reg[ECX].u, Reg[EDX].u) << end();
     Reg[EAX].i = read(/*file descriptor*/Reg[EBX].u, /*memory buffer*/mem_addr_u8(Reg[ECX].u), /*size*/Reg[EDX].u);
     trace(91, "run") << "result: " << Reg[EAX].i << end();
     if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end();
diff --git a/subx/035labels.cc b/subx/035labels.cc
index cbe83802..acbb2206 100644
--- a/subx/035labels.cc
+++ b/subx/035labels.cc
@@ -105,7 +105,7 @@ void compute_byte_indices_for_labels(const segment& code, map<string, int32_t>&
           raise << "'" << to_string(inst) << "': don't use ':' when jumping to labels\n" << end();
         current_byte += 4;
       }
-      else if (has_operand_metadata(curr, "imm16")) {
+      else if (has_operand_metadata(curr, "disp16")) {
         if (*curr.data.rbegin() == ':')
           raise << "'" << to_string(inst) << "': don't use ':' when jumping to labels\n" << end();
         current_byte += 2;
diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1
index 8570b87f..eef31d14 100755
--- a/subx/apps/crenshaw2-1
+++ b/subx/apps/crenshaw2-1
Binary files differdiff --git a/subx/apps/crenshaw2-1.subx b/subx/apps/crenshaw2-1.subx
index fd877f9b..47574d60 100644
--- a/subx/apps/crenshaw2-1.subx
+++ b/subx/apps/crenshaw2-1.subx
@@ -48,6 +48,7 @@
   75/jump-if-not-equal  $run-main/disp8
   # then return run-tests()
   e8/call  run-tests/disp32
+#?   e8/call test-get-num-reads-multiple-digits/disp32
   8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
   eb/jump  $main:end/disp8
 $run-main:
@@ -57,21 +58,134 @@ $run-main:
   8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           0/r32/EAX   .               .                 # copy ESP to EAX
     # clear ed->target (so we really exit)
   c7/copy                         0/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # copy to *EAX
-  # expected(ed, 2/stderr, "integer")
+  # compile(Stdin, 1/stdout, 2/stderr, ed)
     # push args
-  68/push  "integer"/imm32
+  50/push-EAX/ed
   68/push  2/imm32/stderr
-  50/push-EAX
+  68/push  1/imm32/stdout
+  68/push  Stdin/imm32
     # call
-  e8/call  expected/disp32
+  e8/call  compile/disp32
     # discard args
-  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
   # syscall(exit, 0)
   bb/copy-to-EBX  0/imm32
 $main:end:
   b8/copy-to-EAX  1/imm32/exit
   cd/syscall  0x80/imm8
 
+# the main entry point
+compile:  # in : fd or (address stream), out : fd or (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void>
+  # prolog
+  55/push-EBP
+  89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  # save registers
+  50/push-EAX
+  51/push-ECX
+  # Look = get-char(in)
+    # push args
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8      .                    # push *(EBP+8)
+    # call
+  e8/call  get-char/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+  # var num/ECX : (address stream) on the stack
+  # Numbers can be 32 bits or 8 hex bytes long. One of them will be in 'Look', so we need space for 7 bytes.
+  # We won't add more, so that we can get overflow-handling for free.
+  # Add 12 bytes for 'read', 'write' and 'length' fields, for a total of 19 bytes, or 0x13 in hex.
+  81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x13/imm32        # subtract from ESP
+  8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+  # num->length = 7
+  c7/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           .           8/disp8         7/imm32           # copy to *(ECX+8)
+  # clear-stream(num)
+    # push args
+  51/push-ECX
+    # call
+  e8/call  clear-stream/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+  # get-num(in, num, err, ed)
+    # push args
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0x14/disp8      .                 # push *(EBP+20)
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0x10/disp8      .                 # push *(EBP+16)
+  51/push-ECX/num
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8      .                    # push *(EBP+8)
+    # call
+  e8/call  get-num/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
+  # EAX = write(_test-stream, "Ab")
+    # push args
+  68/push  "Ab"/imm32
+  68/push  _test-stream/imm32
+    # call
+  e8/call  write/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+  # EAX = write(out, "bb/copy-to-EBX  ")
+    # push args
+  68/push  "bb/copy-to-EBX  "/imm32
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+    # call
+  e8/call  write/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+  # write-stream(out, num)
+    # push args
+  51/push-ECX/num
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+    # call
+  e8/call  write-stream/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+  # write(out, Newline)
+    # push args
+  68/push  Newline/imm32
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+    # call
+  e8/call  write/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+  # EAX = write(out, "b8/copy-to-EAX  1/imm32/exit")
+    # push args
+  68/push  "b8/copy-to-EAX  1/imm32/exit"/imm32
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+    # call
+  e8/call  write/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+  # EAX = write(out, Newline)
+    # push args
+  68/push  Newline/imm32
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+    # call
+  e8/call  write/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+  # EAX = write(out, "cd/syscall  0x80/imm8")
+    # push args
+  68/push  "cd/syscall  0x80/imm8"/imm32
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+    # call
+  e8/call  write/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+  # EAX = write(out, Newline)
+    # push args
+  68/push  Newline/imm32
+  ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+    # call
+  e8/call  write/disp32
+    # discard args
+  81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+  # restore registers
+  59/pop-to-ECX
+  58/pop-to-EAX
+  # epilog
+  89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+  5d/pop-to-EBP
+  c3/return
+
 # Read a sequence of digits into 'out'. Abort if there are none, or if there
 # are too many to fit in 'out'.
 # Input comes from the global variable 'Look' (first byte) and the argument
@@ -81,7 +195,7 @@ get-num:  # in : (address buffered-file), out : (address stream), err : fd or (a
   #   if !is-digit?(Look) expected(ed, err, "integer")
   #   do
   #     if Look > 0xff
-  #       write(err, "Error: tried to write more than one byte\n")
+  #       write(err, "Error: tried to write too large a value into a single byte\n")
   #       stop(ed, 1)
   #     if out.write >= out.length
   #       write(err, "Error: too many digits in number\n")
@@ -193,7 +307,7 @@ $get-num:loop-stage3:
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
   # if EAX loop
   3d/compare-EAX  0/imm32
-  75/jump-if-not-equal  $get-num:loop/disp8
+  0f 85/jump-if-not-equal  $get-num:loop/disp16
 $get-num:loop-end:
   # persist necessary variables from registers
   89/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           1/r32/ECX   .               .                 # copy ECX to *EDI