diff --git a/part1/build.bat b/part1/build.bat index 83dfefb..3c3a656 100644 --- a/part1/build.bat +++ b/part1/build.bat @@ -220,3 +220,18 @@ nasm %build_dir_listing_0052%_disassembled.asm fc /B %build_dir_listing_0052% %build_dir_listing_0052%_disassembled || exit /b 1 fc /N %build_dir_listing_0052%.txt %build_dir_listing_0052%_disassembled.txt || exit /b 1 + +REM ================================================================================================ +set listing_0053=listing_0053_add_loop_challenge +set build_dir_listing_0053=%build_dir%\%listing_0053% + +copy /Y %script_dir%\%listing_0053% %build_dir% 1>NUL +copy /Y %script_dir%\%listing_0053%.txt %build_dir% 1>NUL + +%build_dir%\sim8086.exe --exec --log-instruction-ptr %build_dir_listing_0053% > %build_dir_listing_0053%_disassembled.txt +%build_dir%\sim8086.exe %build_dir_listing_0053% > %build_dir_listing_0053%_disassembled.asm + +nasm %build_dir_listing_0053%_disassembled.asm + +fc /B %build_dir_listing_0053% %build_dir_listing_0053%_disassembled || exit /b 1 +fc /N %build_dir_listing_0053%.txt %build_dir_listing_0053%_disassembled.txt || exit /b 1 diff --git a/part1/listing_0053_add_loop_challenge b/part1/listing_0053_add_loop_challenge new file mode 100644 index 0000000..0678532 Binary files /dev/null and b/part1/listing_0053_add_loop_challenge differ diff --git a/part1/listing_0053_add_loop_challenge.asm b/part1/listing_0053_add_loop_challenge.asm new file mode 100644 index 0000000..f1ec802 --- /dev/null +++ b/part1/listing_0053_add_loop_challenge.asm @@ -0,0 +1,35 @@ +; ======================================================================== +; +; (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 53 +; ======================================================================== + +bits 16 + +mov dx, 6 +mov bp, 1000 + +mov si, 0 +init_loop_start: + mov word [bp + si], si + add si, 2 + cmp si, dx + jnz init_loop_start + +mov bx, 0 +mov si, dx +sub bp, 2 +add_loop_start: + add bx, word [bp + si] + sub si, 2 + jnz add_loop_start diff --git a/part1/listing_0053_add_loop_challenge.txt b/part1/listing_0053_add_loop_challenge.txt new file mode 100644 index 0000000..79ead2b --- /dev/null +++ b/part1/listing_0053_add_loop_challenge.txt @@ -0,0 +1,36 @@ +--- test\listing_0053_add_loop_challenge execution --- +mov dx, 6 ; dx:0x0->0x6 ip:0x0->0x3 +mov bp, 1000 ; bp:0x0->0x3e8 ip:0x3->0x6 +mov si, 0 ; ip:0x6->0x9 +mov word [bp+si], si ; ip:0x9->0xb +add si, 2 ; si:0x0->0x2 ip:0xb->0xe +cmp si, dx ; ip:0xe->0x10 flags:->CPAS +jne $-7 ; ip:0x10->0x9 +mov word [bp+si], si ; ip:0x9->0xb +add si, 2 ; si:0x2->0x4 ip:0xb->0xe flags:CPAS-> +cmp si, dx ; ip:0xe->0x10 flags:->CAS +jne $-7 ; ip:0x10->0x9 +mov word [bp+si], si ; ip:0x9->0xb +add si, 2 ; si:0x4->0x6 ip:0xb->0xe flags:CAS->P +cmp si, dx ; ip:0xe->0x10 flags:P->PZ +jne $-7 ; ip:0x10->0x12 +mov bx, 0 ; ip:0x12->0x15 +mov si, dx ; ip:0x15->0x17 +sub bp, 2 ; bp:0x3e8->0x3e6 ip:0x17->0x1a flags:PZ-> +add bx, [bp+si] ; bx:0x0->0x4 ip:0x1a->0x1c +sub si, 2 ; si:0x6->0x4 ip:0x1c->0x1f +jne $-5 ; ip:0x1f->0x1a +add bx, [bp+si] ; bx:0x4->0x6 ip:0x1a->0x1c flags:->P +sub si, 2 ; si:0x4->0x2 ip:0x1c->0x1f flags:P-> +jne $-5 ; ip:0x1f->0x1a +add bx, [bp+si] ; ip:0x1a->0x1c flags:->P +sub si, 2 ; si:0x2->0x0 ip:0x1c->0x1f flags:P->PZ +jne $-5 ; ip:0x1f->0x21 + +Final registers: + bx: 0x0006 (6) + dx: 0x0006 (6) + bp: 0x03e6 (998) + ip: 0x0021 (33) + flags: PZ + diff --git a/part1/sim8086.c b/part1/sim8086.c index 78fed17..c9b22e0 100644 --- a/part1/sim8086.c +++ b/part1/sim8086.c @@ -231,19 +231,6 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src) bool effective_addr = ( src && opcode.effective_addr == S86_EffectiveAddress_Src) || (!src && opcode.effective_addr == S86_EffectiveAddress_Dest); - bool wide_prefix = false; - if (opcode.effective_addr == S86_EffectiveAddress_Dest && opcode.effective_addr_loads_mem) { - if (opcode.src == S86_MnemonicOp_DirectAddress || - opcode.src == S86_MnemonicOp_Immediate || - opcode.src == S86_MnemonicOp_Invalid || - (opcode.src >= S86_MnemonicOp_AL && opcode.src <= S86_MnemonicOp_BH) || - (opcode.src == S86_MnemonicOp_SI)) { - // TODO: Not sure why SI needs the prefix as well, but, according - // to the reference decoder its being emitted here. - wide_prefix = (src == false); // NOTE: Only print on the dest op - } - } - if (mnemonic_op == S86_MnemonicOp_Invalid) return; @@ -252,8 +239,8 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src) else S86_PrintFmt(" "); - if (wide_prefix) - S86_PrintFmt("%s ", opcode.wide ? "word" : "byte"); + if (!src && opcode.word_byte_prefix != S86_WordBytePrefix_None) + S86_PrintFmt("%s ", opcode.word_byte_prefix == S86_WordBytePrefix_Word ? "word" : "byte"); if (effective_addr && opcode.seg_reg_prefix != S86_MnemonicOp_Invalid) { S86_Str8 prefix = S86_MnemonicOpStr8(opcode.seg_reg_prefix); @@ -844,6 +831,18 @@ S86_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it, if (op_decode_type != S86_OpDecodeType_SEGMENT) *seg_reg = S86_MnemonicOp_Invalid; + if (result.effective_addr == S86_EffectiveAddress_Dest && result.effective_addr_loads_mem) { + if (result.src == S86_MnemonicOp_DirectAddress || + result.src == S86_MnemonicOp_Immediate || + result.src == S86_MnemonicOp_Invalid || + (result.src >= S86_MnemonicOp_AL && result.src <= S86_MnemonicOp_BH) || + (result.src == S86_MnemonicOp_SI)) { + // TODO: Not sure why SI needs the prefix as well, but, according + // to the reference decoder its being emitted here. + result.word_byte_prefix = result.wide ? S86_WordBytePrefix_Word : S86_WordBytePrefix_Byte; + } + } + 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; @@ -1430,7 +1429,8 @@ int main(int argc, char **argv) src_map = item; } - if (src_map->mnemonic_op >= S86_MnemonicOp_BX_SI && src_map->mnemonic_op <= S86_MnemonicOp_BP_DI) { + if (src_map->mnemonic_op >= S86_MnemonicOp_BX_SI && + src_map->mnemonic_op <= S86_MnemonicOp_BP_DI) { uint16_t address = 0; if (src_map->mnemonic_op == S86_MnemonicOp_BX_SI) { address = src_map->reg->word + register_file.reg.file.si.word; @@ -1524,6 +1524,9 @@ int main(int argc, char **argv) S86_ASSERT(opcode->immediate < S86_CAST(uint16_t)-1); src = S86_CAST(uint16_t)opcode->immediate; } + } else if (opcode->src == S86_MnemonicOp_DirectAddress) { + S86_ASSERT(opcode->displacement >= 0); + src = memory[opcode->displacement]; } else { S86_MnemonicOpToRegisterFileMap const *src_map = NULL; for (size_t index = 0; !src_map && index < S86_ARRAY_UCOUNT(mnemonic_op_to_register_file_map); index++) { @@ -1532,14 +1535,21 @@ int main(int argc, char **argv) src_map = item; } - if (src_map->mnemonic_op == S86_MnemonicOp_BX_SI) { - src = src_map->reg->word + register_file.reg.file.si.word; - } else if (src_map->mnemonic_op == S86_MnemonicOp_BX_DI) { - src = src_map->reg->word + register_file.reg.file.di.word; - } else if (src_map->mnemonic_op == S86_MnemonicOp_BP_SI) { - src = src_map->reg->word + register_file.reg.file.si.word; - } else if (src_map->mnemonic_op == S86_MnemonicOp_BP_DI) { - src = src_map->reg->word + register_file.reg.file.di.word; + if (src_map->mnemonic_op >= S86_MnemonicOp_BX_SI && + src_map->mnemonic_op <= S86_MnemonicOp_BP_DI) { + uint16_t address = 0; + if (src_map->mnemonic_op == S86_MnemonicOp_BX_SI) { + address = src_map->reg->word + register_file.reg.file.si.word; + } else if (src_map->mnemonic_op == S86_MnemonicOp_BX_DI) { + address = src_map->reg->word + register_file.reg.file.di.word; + } else if (src_map->mnemonic_op == S86_MnemonicOp_BP_SI) { + address = src_map->reg->word + register_file.reg.file.si.word; + } else if (src_map->mnemonic_op == S86_MnemonicOp_BP_DI) { + address = src_map->reg->word + register_file.reg.file.di.word; + } else { + S86_ASSERT(!"Invalid code path"); + } + src = *(uint16_t *)&memory[address]; } else { src = byte_op ? src_map->reg->bytes[src_map->byte] : src_map->reg->word; } diff --git a/part1/sim8086.h b/part1/sim8086.h index f21f14d..be05484 100644 --- a/part1/sim8086.h +++ b/part1/sim8086.h @@ -315,6 +315,12 @@ typedef enum S86_EffectiveAddress { S86_EffectiveAddress_Dest, } S86_EffectiveAddress; +typedef enum S86_WordBytePrefix { + S86_WordBytePrefix_None, + S86_WordBytePrefix_Byte, + S86_WordBytePrefix_Word, +} S86_WordBytePrefix; + 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 @@ -325,6 +331,7 @@ typedef struct S86_Opcode { bool lock_prefix; ///< Prefix the opcode with "lock" instruction bool rep_prefix; ///< Prefix the opcode with "rep" instruction bool wide; ///< Opcode has the 'w' flag set + S86_WordBytePrefix word_byte_prefix; ///< Opcode has the 'word' or 'byte' prefix S86_MnemonicOp src; ///< Source op for the mnemonic S86_MnemonicOp dest; ///< Destination op for the mnemonic int32_t displacement; ///< Opcode has displacement/data/offset diff --git a/project.rdbg b/project.rdbg index 06891cc..6c2ed2f 100644 Binary files a/project.rdbg and b/project.rdbg differ