From 00ad047d9a941564b1b56fa7ba58453a9179c7cc Mon Sep 17 00:00:00 2001 From: doyle Date: Sun, 16 Apr 2023 22:29:00 +1000 Subject: [PATCH] perfaware/part1: Support listing 0049 --- part1/build.bat | 15 +++++ part1/listing_0049_conditional_jumps | Bin 0 -> 14 bytes part1/listing_0049_conditional_jumps.asm | 24 +++++++ part1/listing_0049_conditional_jumps.txt | 18 +++++ part1/sim8086.c | 81 ++++++++++++++++++----- part1/sim8086.h | 2 + project.rdbg | Bin 2484 -> 2680 bytes 7 files changed, 124 insertions(+), 16 deletions(-) create mode 100644 part1/listing_0049_conditional_jumps create mode 100644 part1/listing_0049_conditional_jumps.asm create mode 100644 part1/listing_0049_conditional_jumps.txt diff --git a/part1/build.bat b/part1/build.bat index 56b88bd..7b5b776 100644 --- a/part1/build.bat +++ b/part1/build.bat @@ -160,3 +160,18 @@ nasm %build_dir_listing_0048%_disassembled.asm fc /B %build_dir_listing_0048% %build_dir_listing_0048%_disassembled || exit /b 1 fc /N %build_dir_listing_0048%.txt %build_dir_listing_0048%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0049=listing_0049_conditional_jumps +set build_dir_listing_0049=%build_dir%\%listing_0049% + +copy /Y %script_dir%\%listing_0049% %build_dir% 1>NUL +copy /Y %script_dir%\%listing_0049%.txt %build_dir% 1>NUL + +%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0049% > %build_dir_listing_0049%_disassembled.txt +%build_dir%\sim8086.exe %build_dir_listing_0049% > %build_dir_listing_0049%_disassembled.asm + +nasm %build_dir_listing_0049%_disassembled.asm + +fc /B %build_dir_listing_0049% %build_dir_listing_0049%_disassembled || exit /b 1 +fc /N %build_dir_listing_0049%.txt %build_dir_listing_0049%_disassembled.txt || exit /b 1 diff --git a/part1/listing_0049_conditional_jumps b/part1/listing_0049_conditional_jumps new file mode 100644 index 0000000000000000000000000000000000000000..0a27d41ba3ef4b50ff968f7a4bb3b59143ce74a7 GIT binary patch literal 14 VcmdnV%&_|fbMs-Y=9i46KL9OA28{p! literal 0 HcmV?d00001 diff --git a/part1/listing_0049_conditional_jumps.asm b/part1/listing_0049_conditional_jumps.asm new file mode 100644 index 0000000..f80bce6 --- /dev/null +++ b/part1/listing_0049_conditional_jumps.asm @@ -0,0 +1,24 @@ +; ======================================================================== +; +; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved. +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Please see https://computerenhance.com for further information +; +; ======================================================================== + +; ======================================================================== +; LISTING 49 +; ======================================================================== + +bits 16 + +mov cx, 3 +mov bx, 1000 +loop_start: +add bx, 10 +sub cx, 1 +jnz loop_start diff --git a/part1/listing_0049_conditional_jumps.txt b/part1/listing_0049_conditional_jumps.txt new file mode 100644 index 0000000..8005993 --- /dev/null +++ b/part1/listing_0049_conditional_jumps.txt @@ -0,0 +1,18 @@ +--- test\listing_0049_conditional_jumps execution --- +mov cx, 3 ; cx:0x0->0x3 ip:0x0->0x3 +mov bx, 1000 ; bx:0x0->0x3e8 ip:0x3->0x6 +add bx, 10 ; bx:0x3e8->0x3f2 ip:0x6->0x9 flags:->A +sub cx, 1 ; cx:0x3->0x2 ip:0x9->0xc flags:A-> +jne $-6 ; ip:0xc->0x6 +add bx, 10 ; bx:0x3f2->0x3fc ip:0x6->0x9 flags:->P +sub cx, 1 ; cx:0x2->0x1 ip:0x9->0xc flags:P-> +jne $-6 ; ip:0xc->0x6 +add bx, 10 ; bx:0x3fc->0x406 ip:0x6->0x9 flags:->PA +sub cx, 1 ; cx:0x1->0x0 ip:0x9->0xc flags:PA->PZ +jne $-6 ; ip:0xc->0xe + +Final registers: + bx: 0x0406 (1030) + ip: 0x000e (14) + flags: PZ + diff --git a/part1/sim8086.c b/part1/sim8086.c index c6828af..ca7fa92 100644 --- a/part1/sim8086.c +++ b/part1/sim8086.c @@ -237,9 +237,11 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src) opcode.displacement >= 0 ? "" : "-", opcode.displacement >= 0 ? opcode.displacement : -opcode.displacement); } else if (mnemonic_op == S86_MnemonicOp_Jump) { - S86_PrintFmt("$+2%c%d", - opcode.displacement > 0 ? '+' : '-', - opcode.displacement > 0 ? opcode.displacement : -opcode.displacement); + // NOTE: Account for the opcode itself which is 2 bytes, e.g. we can print $+2-8 or just $-6 + int32_t displacement = opcode.displacement + 2; + S86_PrintFmt("$%c%d", + displacement > 0 ? '+' : '-', + displacement > 0 ? displacement : -displacement); } else if (mnemonic_op == S86_MnemonicOp_Immediate) { if (opcode.immediate_is_8bit) { S86_PrintFmt("%d", (int8_t)opcode.immediate); @@ -329,6 +331,7 @@ void S86_DecodeEffectiveAddr(S86_Opcode *opcode, S86_BufferIterator *buffer_it, S86_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it, S86_OpDecode const *decode_table, uint16_t decode_table_size, + uint16_t opcode_index, bool *lock_prefix, S86_MnemonicOp *seg_reg) { @@ -818,6 +821,8 @@ S86_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it, size_t buffer_end_index = buffer_it->index; result.byte_size = S86_CAST(uint8_t)(buffer_end_index - buffer_start_index); + result.instruction_ptr = S86_CAST(uint16_t)buffer_start_index; + result.index = S86_CAST(uint16_t)opcode_index; return result; } @@ -828,6 +833,31 @@ typedef struct S86_MnemonicOpToRegisterFileMap { S86_RegisterByte byte; ///< The 'byte' that the mnemonic operates on (hi, lo or nil e.g. word) } S86_MnemonicOpToRegisterFileMap; +S86_Opcode *S86_OpcodeAtInstructionPtr(S86_Opcode *opcode_array, + size_t opcode_size, + S86_Opcode *prev_opcode, + uint16_t instruction_ptr) +{ + S86_Opcode NIL_OPCODE = {0}; + if (!prev_opcode) + prev_opcode = &NIL_OPCODE; + + S86_Opcode *result = NULL; + if (instruction_ptr < prev_opcode->instruction_ptr) { + for (size_t index = prev_opcode->index - 1; !result && index < opcode_size; index--) { + if (opcode_array[index].instruction_ptr == instruction_ptr) + result = opcode_array + index; + } + } else { + for (size_t index = prev_opcode->index; !result && index < opcode_size; index++) { + if (opcode_array[index].instruction_ptr == instruction_ptr) + result = opcode_array + index; + } + } + + return result; +} + char const CLI_ARG_EXEC[] = "--exec"; char const CLI_ARG_LOG_INSTRUCTION_PTR[] = "--log-instruction-ptr"; #define PRINT_USAGE \ @@ -1213,14 +1243,14 @@ int main(int argc, char **argv) // NOTE: Count opcodes, allocate then decode in 1 swoop // ========================================================================= S86_Opcode *opcode_array = NULL; - size_t opcode_size = 0; + uint16_t opcode_size = 0; { bool lock_prefix = false; S86_MnemonicOp seg_reg = S86_CAST(S86_MnemonicOp)0; for (S86_BufferIterator it = S86_BufferIteratorInit(buffer); S86_BufferIteratorHasMoreBytes(it); opcode_size++) { - S86_DecodeOpcode(&it, DECODE_TABLE, S86_ARRAY_UCOUNT(DECODE_TABLE), &lock_prefix, &seg_reg); + S86_DecodeOpcode(&it, DECODE_TABLE, S86_ARRAY_UCOUNT(DECODE_TABLE), opcode_size, &lock_prefix, &seg_reg); } if (opcode_size == 0) @@ -1234,18 +1264,31 @@ int main(int argc, char **argv) return -1; } - size_t opcode_index = 0; - for (S86_BufferIterator it = S86_BufferIteratorInit(buffer); S86_BufferIteratorHasMoreBytes(it);) { - opcode_array[opcode_index++] = S86_DecodeOpcode(&it, DECODE_TABLE, S86_ARRAY_UCOUNT(DECODE_TABLE), &lock_prefix, &seg_reg); + uint16_t opcode_index = 0; + for (S86_BufferIterator it = S86_BufferIteratorInit(buffer); S86_BufferIteratorHasMoreBytes(it); opcode_index++) { + opcode_array[opcode_index] = S86_DecodeOpcode(&it, DECODE_TABLE, S86_ARRAY_UCOUNT(DECODE_TABLE), opcode_index, &lock_prefix, &seg_reg); } } // NOTE: Execute the assembly // ========================================================================= - for (size_t opcode_index = 0; opcode_index < opcode_size; opcode_index++) { - S86_Opcode *opcode = opcode_array + opcode_index; - S86_PrintOpcode(*opcode); + for (S86_Opcode *prev_opcode = NULL, *opcode = NULL; + register_file.instruction_ptr < buffer.size; + prev_opcode = opcode) { + opcode = S86_OpcodeAtInstructionPtr(opcode_array, + opcode_size, + prev_opcode, + register_file.instruction_ptr); + if (!opcode) { + S86_PrintLnFmt("ERROR: Could not find opcode with matching instruction pointer, execution failed! [file=\"%.*s\", prev_ip=0x%x, ip=0x%x]", + S86_STR8_FMT(file_path), + prev_opcode->instruction_ptr, + register_file.instruction_ptr); + return -1; + } + S86_PrintOpcode(*opcode); + register_file.instruction_ptr += opcode->byte_size; if (opcode->mnemonic == S86_Mnemonic_LOCK || opcode->mnemonic == S86_Mnemonic_SEGMENT) continue; @@ -1254,6 +1297,7 @@ int main(int argc, char **argv) continue; } + // NOTE: Simulate instruction ============================================================== S86_RegisterFileFlags prev_flags = register_file.flags; switch (opcode->mnemonic) { case S86_Mnemonic_PUSH: /*FALLTHRU*/ @@ -1310,7 +1354,6 @@ int main(int argc, char **argv) case S86_Mnemonic_JP_JPE: /*FALLTHRU*/ case S86_Mnemonic_JO: /*FALLTHRU*/ case S86_Mnemonic_JS: /*FALLTHRU*/ - case S86_Mnemonic_JNE_JNZ: /*FALLTHRU*/ case S86_Mnemonic_JNL_JGE: /*FALLTHRU*/ case S86_Mnemonic_JNLE_JG: /*FALLTHRU*/ case S86_Mnemonic_JNB_JAE: /*FALLTHRU*/ @@ -1488,14 +1531,20 @@ int main(int argc, char **argv) } } break; + + case S86_Mnemonic_JNE_JNZ: { + if (!register_file.flags.zero) + register_file.instruction_ptr += S86_CAST(int16_t)opcode->displacement; + S86_PrintFmt(" ; "); + } break; } - // NOTE: Print Instruction Pointer + // NOTE: Printing ========================================================================== + // NOTE: Instruction Pointer if (log_instruction_ptr) - S86_PrintFmt("ip:0x%x->0x%x ", register_file.instruction_ptr, register_file.instruction_ptr + opcode->byte_size); - register_file.instruction_ptr += opcode->byte_size; + S86_PrintFmt("ip:0x%x->0x%x ", opcode->instruction_ptr, register_file.instruction_ptr); - // NOTE: Print Flags + // NOTE: Flags if (!S86_RegisterFileFlagsEq(register_file.flags, prev_flags)) { S86_PrintFmt("flags:"); if (prev_flags.carry) diff --git a/part1/sim8086.h b/part1/sim8086.h index 60752f8..983f598 100644 --- a/part1/sim8086.h +++ b/part1/sim8086.h @@ -323,6 +323,8 @@ typedef enum S86_WidePrefix { typedef struct S86_Opcode { uint8_t byte_size; ///< Number of bytes used to encode this opcode + uint16_t instruction_ptr; ///< The instruction pointer value at this opcode + uint16_t index; ///< Opcode index in the opcode array this was decoded from S86_Mnemonic mnemonic; ///< Mnemonic type S86_EffectiveAddress effective_addr; ///< Src/dest op is an effective address calculation bool effective_addr_loads_mem; ///< Effective address uses '[]' notation to load address memory diff --git a/project.rdbg b/project.rdbg index 3cf1ea31891b4f705cd703ce59d87215f60312d4..8e7dccbf1664c87f371c44c88160e0833283209f 100644 GIT binary patch delta 182 zcmdlY{6l0zEfeciRt5&v$xTdFN+Jvl4EY7g`6;Qob}5;~1v!bysky0nC2Vl<$$OYg z8F?osGP`fKWM0iOxr)t&QFZb~R#8RE_~iV&l+2RM{Jg}R_^i_0f?}X92;c!y?2{Ea zB& delta 77 zcmew%vPF19EfecCRt5&<$xTdFlkYK^GV)B8Wpm#g&Agh0k$ZA2hXEt=