diff options
Diffstat (limited to 'subx')
-rw-r--r-- | subx/010vm.cc | 9 | ||||
-rw-r--r-- | subx/012direct_addressing.cc | 5 | ||||
-rw-r--r-- | subx/014immediate_addressing.cc | 1 | ||||
-rw-r--r-- | subx/018functions.cc | 1 | ||||
-rw-r--r-- | subx/ex7 | bin | 0 -> 156 bytes | |||
-rw-r--r-- | subx/ex7.subx | 90 |
6 files changed, 105 insertions, 1 deletions
diff --git a/subx/010vm.cc b/subx/010vm.cc index e89e2566..0a549982 100644 --- a/subx/010vm.cc +++ b/subx/010vm.cc @@ -147,6 +147,7 @@ inline void write_mem_i32(uint32_t addr, int32_t val) { void run_one_instruction() { uint8_t op=0, op2=0, op3=0; trace(90, "run") << "inst: 0x" << HEXWORD << EIP << end(); +//? dump_registers(); //? cerr << "inst: 0x" << EIP << '\n'; switch (op = next()) { case 0xf4: // hlt @@ -191,6 +192,14 @@ inline uint8_t next() { return read_mem_u8(EIP++); } +void dump_registers() { + for (int i = 0; i < NUM_INT_REGISTERS; ++i) { + if (i > 0) cerr << "; "; + cerr << " " << i << ": " << HEXWORD << Reg[i].u; + } + cerr << '\n'; +} + //: start tracking supported opcodes :(before "End Globals") map</*op*/string, string> name; diff --git a/subx/012direct_addressing.cc b/subx/012direct_addressing.cc index aefe3214..e4f7f8a9 100644 --- a/subx/012direct_addressing.cc +++ b/subx/012direct_addressing.cc @@ -109,7 +109,7 @@ case 0xaf: { // multiply r32 into r/m32 uint8_t arg2 = (modrm>>3)&0x7; trace(90, "run") << "multiply " << rname(arg2) << " into r/m32" << end(); int32_t* arg1 = effective_address(modrm); - BINARY_ARITHMETIC_OP(*, *arg1, Reg[arg2].i); + BINARY_ARITHMETIC_OP(*, Reg[arg2].i, *arg1); break; } @@ -363,6 +363,7 @@ case 0x56: case 0x57: { // push r32 to stack uint8_t reg = op & 0x7; trace(90, "run") << "push " << rname(reg) << end(); +//? cerr << "push: " << NUM(reg) << ": " << Reg[reg].u << " => " << Reg[ESP].u << '\n'; push(Reg[reg].u); break; } @@ -409,7 +410,9 @@ case 0x5e: case 0x5f: { // pop stack into r32 uint8_t reg = op & 0x7; trace(90, "run") << "pop into " << rname(reg) << end(); +//? cerr << "pop from " << Reg[ESP].u << '\n'; Reg[reg].u = pop(); +//? cerr << "=> " << NUM(reg) << ": " << Reg[reg].u << '\n'; break; } :(code) diff --git a/subx/014immediate_addressing.cc b/subx/014immediate_addressing.cc index 8ef36f95..c75c419e 100644 --- a/subx/014immediate_addressing.cc +++ b/subx/014immediate_addressing.cc @@ -469,6 +469,7 @@ put(name, "68", "push imm32 to stack"); case 0x68: { uint32_t val = static_cast<uint32_t>(imm32()); trace(90, "run") << "push imm32 0x" << HEXWORD << val << end(); +//? cerr << "push: " << val << " => " << Reg[ESP].u << '\n'; push(val); trace(90, "run") << "ESP is now 0x" << HEXWORD << Reg[ESP].u << end(); trace(90, "run") << "contents at ESP: 0x" << HEXWORD << read_mem_u32(Reg[ESP].u) << end(); diff --git a/subx/018functions.cc b/subx/018functions.cc index a557abf5..964ca977 100644 --- a/subx/018functions.cc +++ b/subx/018functions.cc @@ -18,6 +18,7 @@ put(name, "e8", "call disp32"); case 0xe8: { // call disp32 relative to next EIP int32_t offset = imm32(); trace(90, "run") << "call imm32 0x" << HEXWORD << offset << end(); +//? cerr << "push: EIP: " << EIP << " => " << Reg[ESP].u << '\n'; push(EIP); EIP += offset; trace(90, "run") << "jumping to 0x" << HEXWORD << EIP << end(); diff --git a/subx/ex7 b/subx/ex7 new file mode 100644 index 00000000..daea2cf4 --- /dev/null +++ b/subx/ex7 Binary files differdiff --git a/subx/ex7.subx b/subx/ex7.subx new file mode 100644 index 00000000..c95ed361 --- /dev/null +++ b/subx/ex7.subx @@ -0,0 +1,90 @@ +## compute the factorial of 5, and return the result in the exit code +# +# To run: +# $ subx translate ex7.subx ex7 +# $ subx run ex7 +# Expected result: +# $ echo $? +# 120 + +== 0x08048054 # code segment, after leaving room for ELF header +# instruction effective address operand displacement immediate +# op subop mod rm32 base index scale r32 +# 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: + # prepare to make a call +# 54 + 55/push # push EBP +# 55 + 89/copy 3/mod/direct 5/rm32/EBP 4/r32/ESP # copy ESP to EBP +# 57 + # factorial(5) + 68/push 5/imm32 # push 5 +# 5c + e8/call factorial/disp32 +# 61 + # discard arg + 5a/pop # pop into EDX +# 62 + # clean up after call + 89/copy 3/mod/direct 4/rm32/ESP 5/r32/EBP # copy EBP to ESP +# 64 + 5d/pop # pop to EBP + + # exit(EAX) +# 65 + 89/copy 3/mod/direct 3/rm32/EBX 0/r32/EAX # copy EAX to EBX +# 67 + b8/copy 1/imm32 # copy 1 to EAX +# 6c + cd/syscall 0x80/imm8 # int 80h + +# factorial(n) +# 6e +factorial: + # initialize n + 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/esp 4/index/none 2/r32/edx 4/disp8 # copy *(ESP+4) to EDX +# 72 + # initialize EAX to 1 (base case) + b8/copy 1/imm32 # copy 1 to EAX +# 77 + # if (n <= 1) jump exit + 81 7/subop/compare 3/mod/direct 2/rm32/EDX 1/imm32 # compare EDX with 1 +# 7d + 7e/jump-if factorial:exit/disp8 # jump if <= to exit +# 7f + # EBX: n-1 + 89/copy 3/mod/direct 3/rm32/EBX 2/r32/EDX # copy EDX to EBX +# 81 + 81 5/subop/subtract 3/mod/direct 3/rm32/EBX 1/imm32 # subtract 1 from EBX +# 87 + # prepare call + 55/push # push EBP +# 88 + 89/copy 3/mod/direct 5/rm32/EBP 4/r32/ESP # copy ESP to EBP + # EAX: factorial(n-1) +# 8a + 53/push # push EBX +# 8b + e8/call factorial/disp32 +# 90 + # discard arg + 5e/pop # pop into ESI +# 91 + # clean up after call + 89/copy 3/mod/direct 4/rm32/ESP 5/r32/EBP # copy EBP to ESP +# 93 + 5d/pop # pop to EBP +# 94 + # refresh n + 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/esp 4/index/none 2/r32/edx 4/disp8 # copy *(ESP+4) to EDX +# 98 + # return n * factorial(n-1) + 0f af/multiply 3/mod/direct 2/rm32/EDX 0/r32/EAX # multiply EDX (n) into EAX (factorial(n-1)) + # TODO: check for overflow +# 9b +factorial:exit: + c3/return + +# vim:ft=subx:nowrap:so=0 |