From 3f2c4fc564fc7169bb64107b5b7655d76c98204c Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 13 May 2019 07:53:31 -0700 Subject: . Make the first instruction described something that doesn't touch flags, so we don't introduce too much complexity all at once. --- subx/011run.cc | 44 ++++++++++++++++++++--------------------- subx/015immediate_addressing.cc | 26 ++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/subx/011run.cc b/subx/011run.cc index ccc891c3..9c1bc4b0 100644 --- a/subx/011run.cc +++ b/subx/011run.cc @@ -65,19 +65,18 @@ void test_add_imm32_to_eax() { // opcode ModR/M SIB displacement immediate // instruction mod, reg, Reg/Mem bits scale, index, base // 1-3 bytes 0/1 byte 0/1 byte 0/1/2/4 bytes 0/1/2/4 bytes - " 05 . . . 0a 0b 0c 0d\n" // add 0x0d0c0b0a to EAX + " b8 . . . 0a 0b 0c 0d\n" // copy 0x0d0c0b0a to EAX // The periods are just to help the eye track long gaps between columns, // and are otherwise ignored. ); // This program, when run, causes the following events in the trace: CHECK_TRACE_CONTENTS( - "load: 0x00000001 -> 05\n" + "load: 0x00000001 -> b8\n" "load: 0x00000002 -> 0a\n" "load: 0x00000003 -> 0b\n" "load: 0x00000004 -> 0c\n" "load: 0x00000005 -> 0d\n" - "run: add imm32 0x0d0c0b0a to reg EAX\n" - "run: storing 0x0d0c0b0a\n" + "run: copy imm32 0x0d0c0b0a to EAX\n" ); } @@ -350,29 +349,30 @@ void parse_and_load(const string& text_bytes) { //:: run :(before "End Initialize Op Names") -put_new(Name, "05", "add imm32 to EAX (add)"); +put_new(Name, "b8", "copy imm32 to EAX (mov)"); -//: our first opcode :(before "End Single-Byte Opcodes") -case 0x05: { // add imm32 to EAX - int32_t signed_arg2 = next32(); - trace(Callstack_depth+1, "run") << "add imm32 0x" << HEXWORD << signed_arg2 << " to reg EAX" << end(); - int64_t signed_full_result = Reg[EAX].i + signed_arg2; - Reg[EAX].i += signed_arg2; - trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[EAX].i << end(); - SF = (Reg[EAX].i < 0); - ZF = (Reg[EAX].i == 0); - OF = (Reg[EAX].i != signed_full_result); - // set CF - uint32_t unsigned_arg1 = static_cast(Reg[EAX].i); - uint32_t unsigned_arg2 = static_cast(signed_arg2); - uint32_t unsigned_result = unsigned_arg1 + unsigned_arg2; - uint64_t unsigned_full_result = unsigned_arg1 + unsigned_arg2; - CF = (unsigned_result != unsigned_full_result); - trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); +case 0xb8: { // copy imm32 to EAX + const int32_t src = next32(); + trace(Callstack_depth+1, "run") << "copy imm32 0x" << HEXWORD << src << " to EAX" << end(); + Reg[EAX].i = src; break; } +:(code) +void test_copy_imm32_to_EAX() { + run( + "== 0x1\n" // code segment + // op ModR/M SIB displacement immediate + " b8 0a 0b 0c 0d \n" // copy 0x0d0c0b0a to EAX + ); + CHECK_TRACE_CONTENTS( + "run: copy imm32 0x0d0c0b0a to EAX\n" + ); +} + +//: our first opcode + :(code) // read a 32-bit int in little-endian order from the instruction stream int32_t next32() { diff --git a/subx/015immediate_addressing.cc b/subx/015immediate_addressing.cc index 8a0ba020..f4762c2b 100644 --- a/subx/015immediate_addressing.cc +++ b/subx/015immediate_addressing.cc @@ -1,5 +1,28 @@ //: instructions that (immediately) contain an argument to act with +:(before "End Initialize Op Names") +put_new(Name, "05", "add imm32 to EAX (add)"); + +:(before "End Single-Byte Opcodes") +case 0x05: { // add imm32 to EAX + int32_t signed_arg2 = next32(); + trace(Callstack_depth+1, "run") << "add imm32 0x" << HEXWORD << signed_arg2 << " to reg EAX" << end(); + int64_t signed_full_result = Reg[EAX].i + signed_arg2; + Reg[EAX].i += signed_arg2; + trace(Callstack_depth+1, "run") << "storing 0x" << HEXWORD << Reg[EAX].i << end(); + SF = (Reg[EAX].i < 0); + ZF = (Reg[EAX].i == 0); + OF = (Reg[EAX].i != signed_full_result); + // set CF + uint32_t unsigned_arg1 = static_cast(Reg[EAX].i); + uint32_t unsigned_arg2 = static_cast(signed_arg2); + uint32_t unsigned_result = unsigned_arg1 + unsigned_arg2; + uint64_t unsigned_full_result = unsigned_arg1 + unsigned_arg2; + CF = (unsigned_result != unsigned_full_result); + trace(Callstack_depth+1, "run") << "SF=" << SF << "; ZF=" << ZF << "; CF=" << CF << "; OF=" << OF << end(); + break; +} + :(before "End Initialize Op Names") put_new(Name, "81", "combine rm32 with imm32 based on subop (add/sub/and/or/xor/cmp)"); @@ -832,7 +855,7 @@ void test_compare_imm32_with_mem_at_r32_equal() { //:: copy (mov) :(before "End Initialize Op Names") -put_new(Name, "b8", "copy imm32 to EAX (mov)"); +// b8 defined earlier to copy imm32 to EAX put_new(Name, "b9", "copy imm32 to ECX (mov)"); put_new(Name, "ba", "copy imm32 to EDX (mov)"); put_new(Name, "bb", "copy imm32 to EBX (mov)"); @@ -854,7 +877,6 @@ void test_copy_imm32_to_r32() { } :(before "End Single-Byte Opcodes") -case 0xb8: case 0xb9: case 0xba: case 0xbb: -- cgit 1.4.1-2-gfad0