From f11c6d0b7fd8a43cd767f9a4293e92bdf4d84c8d Mon Sep 17 00:00:00 2001 From: doyle Date: Sat, 18 Mar 2023 22:31:07 +1100 Subject: [PATCH] perfaware/part1: Get listing 0041 working --- part1/build.bat | 14 ++-- part1/listing_0042_completionist_decode | Bin 852 -> 861 bytes part1/listing_0042_completionist_decode.asm | 12 +++- part1/sim8086.c | 71 +++++++++++++++----- project.rdbg | Bin 1507 -> 1374 bytes 5 files changed, 75 insertions(+), 22 deletions(-) diff --git a/part1/build.bat b/part1/build.bat index f995686..d2fdc1a 100644 --- a/part1/build.bat +++ b/part1/build.bat @@ -11,6 +11,7 @@ copy /Y %script_dir%\listing_0037_single_register_mov %build_dir% 1>NUL copy /Y %script_dir%\listing_0038_many_register_mov %build_dir% 1>NUL copy /Y %script_dir%\listing_0039_more_movs %build_dir% 1>NUL copy /Y %script_dir%\listing_0040_challenge_movs %build_dir% 1>NUL +copy /Y %script_dir%\listing_0041_add_sub_cmp_jnz %build_dir% 1>NUL REM Build REM =========================================================================== @@ -23,19 +24,24 @@ REM =========================================================================== set listing_0037=%build_dir%\listing_0037_single_register_mov %build_dir%\sim8086.exe %listing_0037% > %listing_0037%_disassembled.asm nasm %listing_0037%_disassembled.asm -fc %listing_0037% %listing_0037%_disassembled || exit /b 1 +fc /B %listing_0037% %listing_0037%_disassembled || exit /b 1 set listing_0038=%build_dir%\listing_0038_many_register_mov %build_dir%\sim8086.exe %listing_0038% > %listing_0038%_disassembled.asm nasm %listing_0038%_disassembled.asm -fc %listing_0038% %listing_0038%_disassembled || exit /b 1 +fc /B %listing_0038% %listing_0038%_disassembled || exit /b 1 set listing_0039=%build_dir%\listing_0039_more_movs %build_dir%\sim8086.exe %listing_0039% > %listing_0039%_disassembled.asm nasm %listing_0039%_disassembled.asm -fc %listing_0039% %listing_0039%_disassembled || exit /b 1 +fc /B %listing_0039% %listing_0039%_disassembled || exit /b 1 set listing_0040=%build_dir%\listing_0040_challenge_movs %build_dir%\sim8086.exe %listing_0040% > %listing_0040%_disassembled.asm nasm %listing_0040%_disassembled.asm -fc %listing_0040% %listing_0040%_disassembled || exit /b 1 +fc /B %listing_0040% %listing_0040%_disassembled || exit /b 1 + +set listing_0041=%build_dir%\listing_0041_add_sub_cmp_jnz +%build_dir%\sim8086.exe %listing_0041% > %listing_0041%_disassembled.asm +nasm %listing_0041%_disassembled.asm +fc /B %listing_0041% %listing_0041%_disassembled || exit /b 1 diff --git a/part1/listing_0042_completionist_decode b/part1/listing_0042_completionist_decode index c200467f7627dcd9d0ad7ff0870c0462aae6889d..973a32a464439e99acf13019acbc159b1e1ebf72 100644 GIT binary patch delta 24 gcmcb@c9(4fH#6gz$-K<&T(eFvRx`X(Vi08p0A`8@KL7v# delta 14 Vcmcc1c7<&NH#5^&=E*$F?f@mH1UCQx diff --git a/part1/listing_0042_completionist_decode.asm b/part1/listing_0042_completionist_decode.asm index 894bdf8..ef709e0 100644 --- a/part1/listing_0042_completionist_decode.asm +++ b/part1/listing_0042_completionist_decode.asm @@ -332,7 +332,7 @@ rep cmpsw rep scasw rep lodsw -; NOTE(casey): Special thanks (as always!) to Mārtiņš Možeiko for figuring out why NASM +; NOTE(casey): Special thanks (as always!) to Mārtiņš Možeiko for figuring out why NASM ; wouldn't compile "rep stds" instructions. It was because it was a misprint in the 8086 ; manual! It was really just "rep stos", which of course is still in x64, and NASM ; assembles it just fine. @@ -376,7 +376,7 @@ loopnz label jcxz label int 13 -int 3 +int3 into iret @@ -408,6 +408,14 @@ sbb word cs:[bx + si - 4332], 10328 lock not byte CS:[bp + 9905] +; +; NOTE(casey): These were not in the original homework set, but have been added since, as people +; found instruction encodings that were not previously covered +; + +call 123:456 +jmp 789:34 + ; ; TODO(casey): I would like to uncomment this, but as far as I can tell, NASM doesn't recognize the ESC instruction :( ; so even if I just force the assembler to output the bits here, our disasm will fail to assemble because it will (correctly!) diff --git a/part1/sim8086.c b/part1/sim8086.c index 324715f..052ea30 100644 --- a/part1/sim8086.c +++ b/part1/sim8086.c @@ -108,7 +108,7 @@ typedef enum S86_InstructionType { S86_InstructionType_LOOP, S86_InstructionType_LOOPZ_LOOPE, S86_InstructionType_LOOPNZ_LOOPNE, - S86_InstructionType_JCZX, + S86_InstructionType_JCXZ, S86_InstructionType_Count, } S86_InstructionType; @@ -242,7 +242,7 @@ void S86_FileFree(S86_Buffer buffer) VirtualFree(buffer.data, 0, MEM_RELEASE); } -void S86_PrintLn(S86_Str8 string) +void S86_Print(S86_Str8 string) { if (s86_globals.stdout_handle == NULL) { s86_globals.stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); @@ -259,14 +259,38 @@ void S86_PrintLn(S86_Str8 string) if (s86_globals.write_to_console) { DWORD chars_written = 0; WriteConsoleA(s86_globals.stdout_handle, string.data, (DWORD)string.size, &chars_written, NULL); - WriteConsoleA(s86_globals.stdout_handle, "\n", 1, &chars_written, NULL); } else { DWORD bytes_written = 0; WriteFile(s86_globals.stdout_handle, string.data, (DWORD)string.size, &bytes_written, NULL); - WriteFile(s86_globals.stdout_handle, "\n", 1, &bytes_written, NULL); } } +void S86_PrintLn(S86_Str8 string) +{ + S86_Print(string); + S86_Print(S86_STR8("\n")); +} + +void S86_PrintFmt(char const *fmt, ...) +{ + va_list args, args_copy; + va_start(args, fmt); + + va_copy(args_copy, args); + int string_size = vsnprintf(NULL, 0, fmt, args_copy); + va_end(args_copy); + + char buffer[8192]; + S86_ASSERT(string_size >= 0 && string_size < S86_ARRAY_UCOUNT(buffer)); + if (string_size) { + vsnprintf(buffer, sizeof(buffer), fmt, args); + S86_Str8 string = {.data = buffer, .size = string_size}; + S86_Print(string); + } + + va_end(args); +} + void S86_PrintLnFmt(char const *fmt, ...) { va_list args, args_copy; @@ -420,9 +444,9 @@ S86_Instruction const S86_INSTRUCTIONS[S86_InstructionType_Count] = { [S86_InstructionType_CMPImmediateWithAccum] = {.op_mask0 = 0b1111'1110, .op_mask1 = 0b0000'0000, .op_bits0 = 0b0011'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("cmp")}, [S86_InstructionType_JE_JZ] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jz")}, + .op_bits0 = 0b0111'0100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("je")}, [S86_InstructionType_JL_JNGE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jl")}, + .op_bits0 = 0b0111'1100, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jl")}, [S86_InstructionType_JLE_JNG] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, .op_bits0 = 0b0111'1110, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jle")}, [S86_InstructionType_JB_JNAE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, @@ -436,15 +460,15 @@ S86_Instruction const S86_INSTRUCTIONS[S86_InstructionType_Count] = { [S86_InstructionType_JS] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, .op_bits0 = 0b0111'1000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("js")}, [S86_InstructionType_JNE_JNZ] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jne")}, + .op_bits0 = 0b0111'0101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jnz")}, [S86_InstructionType_JNL_JGE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, .op_bits0 = 0b0111'1101, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jnl")}, [S86_InstructionType_JNLE_JG] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jnle")}, + .op_bits0 = 0b0111'1111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jg")}, [S86_InstructionType_JNB_JAE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, .op_bits0 = 0b0111'0011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jnb")}, [S86_InstructionType_JNBE_JA] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b0111'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jnbe")}, + .op_bits0 = 0b0111'0111, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("ja")}, [S86_InstructionType_JNP_JO] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, .op_bits0 = 0b0111'1011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jnp")}, [S86_InstructionType_JNO] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, @@ -457,8 +481,8 @@ S86_Instruction const S86_INSTRUCTIONS[S86_InstructionType_Count] = { .op_bits0 = 0b1110'0001, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("loopz")}, [S86_InstructionType_LOOPNZ_LOOPNE] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, .op_bits0 = 0b1110'0000, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("loopnz")}, - [S86_InstructionType_JCZX] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, - .op_bits0 = 0b1110'0011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jczx")}, + [S86_InstructionType_JCXZ] = {.op_mask0 = 0b1111'1111, .op_mask1 = 0b0000'0000, + .op_bits0 = 0b1110'0011, .op_bits1 = 0b0000'0000, .mnemonic = S86_STR8("jcxz")}, }; @@ -590,10 +614,18 @@ S86_Instruction const S86_INSTRUCTIONS[S86_InstructionType_Count] = { if (instruction_type == S86_InstructionType_MOVImmediateToRegOrMem) { S86_PrintLnFmt("%.*s %.*s, %s %u", S86_STR8_FMT(instruction->mnemonic), effective_address.size, effective_address.data, w ? "word" : "byte", data); } else { - if (sign_extend_8bit_data) { - S86_PrintLnFmt("%.*s %.*s, %d", S86_STR8_FMT(instruction->mnemonic), effective_address.size, effective_address.data, (int16_t)data); + if (effective_address.data[0] == '[') { + if (sign_extend_8bit_data) { + S86_PrintLnFmt("%.*s %s %.*s, %d", S86_STR8_FMT(instruction->mnemonic), w ? "word" : "byte", effective_address.size, effective_address.data, (int16_t)data); + } else { + S86_PrintLnFmt("%.*s %s %.*s, %u", S86_STR8_FMT(instruction->mnemonic), w ? "word" : "byte", effective_address.size, effective_address.data, data); + } } else { - S86_PrintLnFmt("%.*s %.*s, %u", S86_STR8_FMT(instruction->mnemonic), effective_address.size, effective_address.data, data); + if (sign_extend_8bit_data) { + S86_PrintLnFmt("%.*s %.*s, %d", S86_STR8_FMT(instruction->mnemonic), effective_address.size, effective_address.data, (int16_t)data); + } else { + S86_PrintLnFmt("%.*s %.*s, %u", S86_STR8_FMT(instruction->mnemonic), effective_address.size, effective_address.data, data); + } } } } break; @@ -661,10 +693,17 @@ S86_Instruction const S86_INSTRUCTIONS[S86_InstructionType_Count] = { } break; default: { - if (instruction_type >= S86_InstructionType_JE_JZ && instruction_type <= S86_InstructionType_JCZX) { + if (instruction_type >= S86_InstructionType_JE_JZ && instruction_type <= S86_InstructionType_JCXZ) { S86_ASSERT(op_code_size == 1); int8_t jump_offset = S86_CAST(int8_t)S86_BufferIteratorNextByte(&buffer_it); - S86_PrintLnFmt("%.*s %d", S86_STR8_FMT(instruction->mnemonic), jump_offset); + char sign = 0; + if (jump_offset > 0) { + sign = '+'; + } else { + jump_offset *= -1; + sign = '-'; + } + S86_PrintLnFmt("%.*s $+2%c%d", S86_STR8_FMT(instruction->mnemonic), sign, jump_offset); } else { S86_ASSERT(!"Unhandled instruction"); } diff --git a/project.rdbg b/project.rdbg index b3f9a964378335d50f29c3a96e1217ac67ebe3aa..c6145f073230e1ae43cef5ffef211395c2f11322 100644 GIT binary patch delta 153 zcmaFNeUEFxL0%RH2w((K_LCKuEhn=xu3|E0nw-cO;M2&&zyMOf3&i;a@yYoqsqsmb zC8@v(seqMY@WkD)8s+b6ntC5*kVi8}WnUYyt zkdv64nwy$e0&+t+$fCre)Z)^d5}>(UKpsd*d`>dGkGJ6&g26uvXc{-*e1_m;YAW@U=f;pm!%N^ Dwx(8V