perfaware/part1: Support listing 0049

This commit is contained in:
doyle 2023-04-16 22:29:00 +10:00
parent 6f0715b0ca
commit 00ad047d9a
7 changed files with 124 additions and 16 deletions

View File

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

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

Binary file not shown.