diff options
author | Kartik Agaram <vc@akkartik.com> | 2018-09-22 23:19:39 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2018-09-22 23:19:39 -0700 |
commit | 7d4e351a0d1e3c4e71b58d3218b4e6b833f542f2 (patch) | |
tree | 8f8b8e62848b76ce5debf3ef89ad6f0e1c381de8 | |
parent | 2b36eee9b13eb16fb2e4b05d7e26f6d09f431912 (diff) | |
download | mu-7d4e351a0d1e3c4e71b58d3218b4e6b833f542f2.tar.gz |
4503
Include LEA (load effective address) in the SubX subset of x86 ISA.
-rw-r--r-- | subx/013direct_addressing.cc | 18 | ||||
-rw-r--r-- | subx/014indirect_addressing.cc | 23 | ||||
-rw-r--r-- | subx/031check_operands.cc | 2 | ||||
-rwxr-xr-x | subx/examples/ex5 | bin | 138 -> 139 bytes | |||
-rw-r--r-- | subx/examples/ex5.subx | 7 | ||||
-rwxr-xr-x | subx/examples/ex8 | bin | 149 -> 143 bytes | |||
-rw-r--r-- | subx/examples/ex8.subx | 6 |
7 files changed, 42 insertions, 14 deletions
diff --git a/subx/013direct_addressing.cc b/subx/013direct_addressing.cc index 0ddb1ce8..7b265a44 100644 --- a/subx/013direct_addressing.cc +++ b/subx/013direct_addressing.cc @@ -32,19 +32,31 @@ int32_t* effective_address(uint8_t modrm) { uint8_t mod = (modrm>>6); // ignore middle 3 'reg opcode' bits uint8_t rm = modrm & 0x7; + if (mod == 3) { + // mod 3 is just register direct addressing + trace(90, "run") << "r/m32 is " << rname(rm) << end(); + return &Reg[rm].i; + } + return mem_addr_i32(effective_address_number(modrm)); +} + +uint32_t effective_address_number(uint8_t modrm) { + uint8_t mod = (modrm>>6); + // ignore middle 3 'reg opcode' bits + uint8_t rm = modrm & 0x7; uint32_t addr = 0; switch (mod) { case 3: // mod 3 is just register direct addressing - trace(90, "run") << "r/m32 is " << rname(rm) << end(); - return &Reg[rm].i; + raise << "unexpected direct addressing mode\n" << end(); + return 0; // End Mod Special-cases(addr) default: cerr << "unrecognized mod bits: " << NUM(mod) << '\n'; exit(1); } //: other mods are indirect, and they'll set addr appropriately - return mem_addr_i32(addr); + return addr; } string rname(uint8_t r) { diff --git a/subx/014indirect_addressing.cc b/subx/014indirect_addressing.cc index ccbf994c..b48cbd85 100644 --- a/subx/014indirect_addressing.cc +++ b/subx/014indirect_addressing.cc @@ -641,3 +641,26 @@ case 2: // indirect + disp32 addressing +run: effective address is initially 0x61 (EAX) +run: effective address is 0x60 (after adding disp32) +run: storing 0x00000011 + +//:: lea + +:(before "End Initialize Op Names(name)") +put(name, "8d", "load effective address of memory in rm32 into r32"); + +:(scenario lea) +% Reg[EAX].u = 0x60; +== 0x1 +# op ModR/M SIB displacement immediate + 8d 18 +# ModR/M in binary: 00 (indirect mode) 011 (dest EBX) 000 (src EAX) ++run: lea into EBX ++run: effective address is 0x60 (EAX) + +:(before "End Single-Byte Opcodes") +case 0x8d: { // lea m32 to r32 + uint8_t modrm = next(); + uint8_t arg1 = (modrm>>3)&0x7; + trace(90, "run") << "lea into " << rname(arg1) << end(); + Reg[arg1].u = effective_address_number(modrm); + break; +} diff --git a/subx/031check_operands.cc b/subx/031check_operands.cc index 5f99f7b0..f24eb62c 100644 --- a/subx/031check_operands.cc +++ b/subx/031check_operands.cc @@ -214,6 +214,8 @@ void init_permitted_operands() { put(Permitted_operands, "8b", 0x01); // swap put(Permitted_operands, "87", 0x01); + // lea + put(Permitted_operands, "8d", 0x01); // pop put(Permitted_operands, "8f", 0x01); diff --git a/subx/examples/ex5 b/subx/examples/ex5 index 536ddcd6..906846db 100755 --- a/subx/examples/ex5 +++ b/subx/examples/ex5 Binary files differdiff --git a/subx/examples/ex5.subx b/subx/examples/ex5.subx index faecdcfb..51bc19a0 100644 --- a/subx/examples/ex5.subx +++ b/subx/examples/ex5.subx @@ -10,9 +10,6 @@ # 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # main: - # prolog - 55/push-EBP - 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # allocate x on the stack 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # subtract 4 bytes from ESP @@ -20,7 +17,7 @@ # fd = 0 (stdin) bb/copy . . . . . . . 0/imm32 # copy 0 to EBX # initialize x (location to write result to) - 89/copy 3/mod/direct 1/rm32/ECX . . . 5/r32/EBP . . # copy EBP to ECX + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none 1/r32/ECX 4/disp8 . # copy ESP+4 to ECX # size = 1 character ba/copy . . . . . . . 1/imm32 # copy 1 to EDX # read(fd, x, size) @@ -31,7 +28,7 @@ # fd = 1 (stdout) bb/copy . . . . . . . 1/imm32 # copy 1 to EBX # initialize x (location to read from) - 89/copy 3/mod/direct 1/rm32/ECX . . . 5/r32/EBP . . # copy EBP to ECX + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none 1/r32/ECX 4/disp8 . # copy ESP+4 to ECX # size = 1 character ba/copy . . . . . . . 1/imm32 # copy 1 to EDX # write(fd, x, size) diff --git a/subx/examples/ex8 b/subx/examples/ex8 index c0aa5806..463f83b8 100755 --- a/subx/examples/ex8 +++ b/subx/examples/ex8 Binary files differdiff --git a/subx/examples/ex8.subx b/subx/examples/ex8.subx index 8d9efcd7..fb35dc7e 100644 --- a/subx/examples/ex8.subx +++ b/subx/examples/ex8.subx @@ -21,18 +21,12 @@ # var s = argv[1] (EBX) 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none 3/r32/EBX 8/disp8 . # copy *(ESP+8) to EBX # call ascii_length(EBX) - # prepare call - 55/push-EBP - 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP # push args 53/push-EBX # call e8/call ascii_length/disp32 # discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add 4 to ESP - # clean up after call - 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 5d/pop-to-EBP # exit(EAX) 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX |