diff options
-rw-r--r-- | subx/014indirect_addressing.cc | 19 | ||||
-rwxr-xr-x | subx/examples/ex10 | bin | 155 -> 276 bytes | |||
-rw-r--r-- | subx/examples/ex10.subx | 77 |
3 files changed, 88 insertions, 8 deletions
diff --git a/subx/014indirect_addressing.cc b/subx/014indirect_addressing.cc index 9142728a..ccbf994c 100644 --- a/subx/014indirect_addressing.cc +++ b/subx/014indirect_addressing.cc @@ -388,16 +388,18 @@ case 0x8b: { // copy r32 to r/m32 put(name, "88", "copy r8 (lowermost byte of r32) to r8/m8-at-r32"); :(scenario copy_r8_to_mem_at_r32) -% Reg[EBX].i = 0xafafafaf; +% Reg[EBX].i = 0x224488ab; % Reg[EAX].i = 0x60; == 0x1 # op ModR/M SIB displacement immediate 88 18 # copy just the lowermost byte of EBX to the byte at *EAX # ModR/M in binary: 00 (indirect mode) 011 (src EBX) 000 (dest EAX) +== 0x60 +f0 cc bb aa # 0xf0 with more data in following bytes +run: copy lowermost byte of EBX to r8/m8-at-r32 +run: effective address is 0x60 (EAX) -+run: storing 0xaf -% CHECK_EQ(0x000000af, read_mem_u32(0x60)); ++run: storing 0xab +% CHECK_EQ(0xaabbccab, read_mem_u32(0x60)); :(before "End Single-Byte Opcodes") case 0x88: { // copy r/m8 to r8 @@ -417,17 +419,19 @@ case 0x88: { // copy r/m8 to r8 put(name, "8a", "copy r8/m8-at-r32 to r8 (lowermost byte of r32)"); :(scenario copy_mem_at_r32_to_r8) -% Reg[EBX].i = 0xaf; +% Reg[EBX].i = 0xaabbcc0f; // one nibble each of lowest byte set to all 0s and all 1s, to maximize value of this test % Reg[EAX].i = 0x60; == 0x1 # op ModR/M SIB displacement immediate 8a 18 # copy just the byte at *EAX to lowermost byte of EBX (clearing remaining bytes) # ModR/M in binary: 00 (indirect mode) 011 (dest EBX) 000 (src EAX) == 0x60 # data segment -af ff ff ff # 0xaf with more data in following bytes +ab ff ff ff # 0xab with more data in following bytes +run: copy r8/m8-at-r32 to lowermost byte of EBX +run: effective address is 0x60 (EAX) -+run: storing 0xaf ++run: storing 0xab +# remaining bytes of EBX are *not* cleared ++run: EBX now contains 0xaabbccab :(before "End Single-Byte Opcodes") case 0x8a: { // copy r/m8 to r8 @@ -436,8 +440,9 @@ case 0x8a: { // copy r/m8 to r8 trace(90, "run") << "copy r8/m8-at-r32 to lowermost byte of " << rname(reg1) << end(); // use unsigned to zero-extend 8-bit value to 32 bits uint8_t* arg2 = reinterpret_cast<uint8_t*>(effective_address(modrm)); - Reg[reg1].u = static_cast<uint32_t>(*arg2); trace(90, "run") << "storing 0x" << HEXBYTE << NUM(*arg2) << end(); + *reinterpret_cast<uint8_t*>(&Reg[reg1].u) = *arg2; // assumes host is little-endian + trace(90, "run") << rname(reg1) << " now contains 0x" << HEXWORD << Reg[reg1].u << end(); break; } diff --git a/subx/examples/ex10 b/subx/examples/ex10 index ddfd6c30..cd3de11e 100755 --- a/subx/examples/ex10 +++ b/subx/examples/ex10 Binary files differdiff --git a/subx/examples/ex10.subx b/subx/examples/ex10.subx index 321cee64..1a426e28 100644 --- a/subx/examples/ex10.subx +++ b/subx/examples/ex10.subx @@ -26,9 +26,11 @@ # push args 50/push . . . . . . . . # push EAX 53/push . . . . . . . . # push EBX +#? e8/call write_argv_3/disp32 # call - e8/call argv_equal/disp32 + e8/call argv_equal/disp32 # exit(EAX) +$exit: 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX b8/copy . . . . . . . 1/imm32 # copy 1 to EAX cd/syscall 0x80/imm8 @@ -39,11 +41,18 @@ argv_equal: # (s1, s2) : null-terminated ascii strings -> EAX : boolean # initialize s1 (ECX) and s2 (EDX) 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 1/r32/ECX 8/disp8 . # copy *(ESP+8) to ECX 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 2/r32/EDX 4/disp8 . # copy *(ESP+4) to EDX +#? # i/ESI = 0 +#? be/copy 0/imm32 # copy 0 to ESI # while (true) $argv_loop: # c1/EAX, c2/EBX = *s1, *s2 + b8/copy 0/imm32 # clear EAX 8a/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy byte at *ECX to lower byte of EAX + bb/copy 0/imm32 # clear EBX 8a/copy 0/mod/indirect 2/rm32/EDX . . . 3/r32/EBX . . # copy byte at *EDX to lower byte of EBX +#? # if (i == _) exit(EAX) +#? 81 7/subop 3/mod/direct 6/rm32/ESI 3/imm32 # compare ESI with _ +#? 74/jump-if-equal $exit/disp8 # if (c1 == 0) break 3d/compare . . . . . . . 0/imm32 # compare EAX with 0 74/jump-if-equal $argv_break/disp8 @@ -53,7 +62,15 @@ $argv_loop: # ++s1, ++s2 41/inc-ECX 42/inc-EDX +#? # ++i +#? 46/inc-ESI # end while +#? 68/push X/imm32 +#? e8/call write_stderr/disp32 +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP 4/imm32 # add 4 to ESP +#? 51/push . . . . . . . . # push ECX +#? e8/call write_argv_3/disp32 +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP 4/imm32 # add 4 to ESP eb/jump $argv_loop/disp8 $argv_break: # if (c2 == 0) return true @@ -65,3 +82,61 @@ $argv_break: $argv_fail: b8/copy . . . . . . . 0/imm32 # copy 0 to EAX c3/return + +write_stderr: # s : (address array byte) -> <void> + # save registers + 50/push . . . . . . . . # push EAX + 51/push . . . . . . . . # push ECX + 52/push . . . . . . . . # push EDX + 53/push . . . . . . . . # push EBX + # write(2/stderr, (data) s+4, (size) *s) + # fd = 2 (stderr) + bb/copy . . . . . . . 2/imm32 # copy 2 to EBX + # x = s+4 + 8b/copy 1/mod/*+disp8 4/rm32/SIB 4/base/ESP 4/index/none . 1/r32/ECX 0x14/disp8 . # copy *(ESP+20) to ECX + 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 4/imm32 # add 4 to ECX + # size = *s + 8b/copy 1/mod/*+disp8 4/rm32/SIB 4/base/ESP 4/index/none . 2/r32/EDX 0x14/disp8 . # copy *(ESP+20) to EDX + 8b/copy 0/mod/indirect 2/rm32/EDX . . . 2/r32/EDX . . # copy *EDX to EDX + # call write() + b8/copy . . . . . . . 4/imm32/write # copy 1 to EAX + cd/syscall 0x80/imm8 + # restore registers + 5b/pop . . . . . . . . # pop EBX + 5a/pop . . . . . . . . # pop EDX + 59/pop . . . . . . . . # pop ECX + 58/pop . . . . . . . . # pop EAX + # end + c3/return + +write_argv_3: # s : null-terminated ascii string of size exactly 3 -> <void> + # save registers + 50/push . . . . . . . . # push EAX + 51/push . . . . . . . . # push ECX + 52/push . . . . . . . . # push EDX + 53/push . . . . . . . . # push EBX + # write(2/stderr, (data) s+4, (size) *s) + # fd = 2 (stderr) + bb/copy . . . . . . . 2/imm32 # copy 2 to EBX + # x = s + 8b/copy 1/mod/*+disp8 4/rm32/SIB 4/base/ESP 4/index/none . 1/r32/ECX 0x14/disp8 . # copy *(ESP+20) to ECX + # size = 3 + ba/copy . . . . . . . 3/imm32 # copy 3 to EDX (hardcoded) + # call write() + b8/copy . . . . . . . 4/imm32/write # copy 1 to EAX + cd/syscall 0x80/imm8 + # restore registers + 5b/pop . . . . . . . . # pop EBX + 5a/pop . . . . . . . . # pop EDX + 59/pop . . . . . . . . # pop ECX + 58/pop . . . . . . . . # pop EAX + # end + c3/return + +== data +X: + 02 00 00 00 + 58/X 0a/newline +Y: + 02 00 00 00 + 59/Y 0a/newline |