perfaware/part1: Get listing 0041 working

This commit is contained in:
doyle 2023-03-18 22:31:07 +11:00 committed by committed-name
parent f5316a08fc
commit f11c6d0b7f
5 changed files with 75 additions and 22 deletions

View File

@ -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

View File

@ -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!)

View File

@ -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")},
};
@ -589,6 +613,13 @@ 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 (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 {
if (sign_extend_8bit_data) {
S86_PrintLnFmt("%.*s %.*s, %d", S86_STR8_FMT(instruction->mnemonic), effective_address.size, effective_address.data, (int16_t)data);
@ -596,6 +627,7 @@ S86_Instruction const S86_INSTRUCTIONS[S86_InstructionType_Count] = {
S86_PrintLnFmt("%.*s %.*s, %u", S86_STR8_FMT(instruction->mnemonic), effective_address.size, effective_address.data, data);
}
}
}
} break;
case S86_InstructionType_CMPImmediateWithAccum: /*FALLTHRU*/
@ -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");
}

Binary file not shown.