perfaware/part1: Support listing 0049
This commit is contained in:
parent
6f0715b0ca
commit
00ad047d9a
@ -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 /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
|
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
|
||||||
|
BIN
part1/listing_0049_conditional_jumps
Normal file
BIN
part1/listing_0049_conditional_jumps
Normal file
Binary file not shown.
24
part1/listing_0049_conditional_jumps.asm
Normal file
24
part1/listing_0049_conditional_jumps.asm
Normal 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
|
18
part1/listing_0049_conditional_jumps.txt
Normal file
18
part1/listing_0049_conditional_jumps.txt
Normal 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
|
||||||
|
|
@ -237,9 +237,11 @@ void S86_PrintOpcodeMnemonicOp(S86_Opcode opcode, bool src)
|
|||||||
opcode.displacement >= 0 ? "" : "-",
|
opcode.displacement >= 0 ? "" : "-",
|
||||||
opcode.displacement >= 0 ? opcode.displacement : -opcode.displacement);
|
opcode.displacement >= 0 ? opcode.displacement : -opcode.displacement);
|
||||||
} else if (mnemonic_op == S86_MnemonicOp_Jump) {
|
} else if (mnemonic_op == S86_MnemonicOp_Jump) {
|
||||||
S86_PrintFmt("$+2%c%d",
|
// NOTE: Account for the opcode itself which is 2 bytes, e.g. we can print $+2-8 or just $-6
|
||||||
opcode.displacement > 0 ? '+' : '-',
|
int32_t displacement = opcode.displacement + 2;
|
||||||
opcode.displacement > 0 ? opcode.displacement : -opcode.displacement);
|
S86_PrintFmt("$%c%d",
|
||||||
|
displacement > 0 ? '+' : '-',
|
||||||
|
displacement > 0 ? displacement : -displacement);
|
||||||
} else if (mnemonic_op == S86_MnemonicOp_Immediate) {
|
} else if (mnemonic_op == S86_MnemonicOp_Immediate) {
|
||||||
if (opcode.immediate_is_8bit) {
|
if (opcode.immediate_is_8bit) {
|
||||||
S86_PrintFmt("%d", (int8_t)opcode.immediate);
|
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_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it,
|
||||||
S86_OpDecode const *decode_table,
|
S86_OpDecode const *decode_table,
|
||||||
uint16_t decode_table_size,
|
uint16_t decode_table_size,
|
||||||
|
uint16_t opcode_index,
|
||||||
bool *lock_prefix,
|
bool *lock_prefix,
|
||||||
S86_MnemonicOp *seg_reg)
|
S86_MnemonicOp *seg_reg)
|
||||||
{
|
{
|
||||||
@ -818,6 +821,8 @@ S86_Opcode S86_DecodeOpcode(S86_BufferIterator *buffer_it,
|
|||||||
|
|
||||||
size_t buffer_end_index = buffer_it->index;
|
size_t buffer_end_index = buffer_it->index;
|
||||||
result.byte_size = S86_CAST(uint8_t)(buffer_end_index - buffer_start_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;
|
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_RegisterByte byte; ///< The 'byte' that the mnemonic operates on (hi, lo or nil e.g. word)
|
||||||
} S86_MnemonicOpToRegisterFileMap;
|
} 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_EXEC[] = "--exec";
|
||||||
char const CLI_ARG_LOG_INSTRUCTION_PTR[] = "--log-instruction-ptr";
|
char const CLI_ARG_LOG_INSTRUCTION_PTR[] = "--log-instruction-ptr";
|
||||||
#define PRINT_USAGE \
|
#define PRINT_USAGE \
|
||||||
@ -1213,14 +1243,14 @@ int main(int argc, char **argv)
|
|||||||
// NOTE: Count opcodes, allocate then decode in 1 swoop
|
// NOTE: Count opcodes, allocate then decode in 1 swoop
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
S86_Opcode *opcode_array = NULL;
|
S86_Opcode *opcode_array = NULL;
|
||||||
size_t opcode_size = 0;
|
uint16_t opcode_size = 0;
|
||||||
{
|
{
|
||||||
bool lock_prefix = false;
|
bool lock_prefix = false;
|
||||||
S86_MnemonicOp seg_reg = S86_CAST(S86_MnemonicOp)0;
|
S86_MnemonicOp seg_reg = S86_CAST(S86_MnemonicOp)0;
|
||||||
for (S86_BufferIterator it = S86_BufferIteratorInit(buffer);
|
for (S86_BufferIterator it = S86_BufferIteratorInit(buffer);
|
||||||
S86_BufferIteratorHasMoreBytes(it);
|
S86_BufferIteratorHasMoreBytes(it);
|
||||||
opcode_size++) {
|
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)
|
if (opcode_size == 0)
|
||||||
@ -1234,18 +1264,31 @@ int main(int argc, char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t opcode_index = 0;
|
uint16_t opcode_index = 0;
|
||||||
for (S86_BufferIterator it = S86_BufferIteratorInit(buffer); S86_BufferIteratorHasMoreBytes(it);) {
|
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), &lock_prefix, &seg_reg);
|
opcode_array[opcode_index] = S86_DecodeOpcode(&it, DECODE_TABLE, S86_ARRAY_UCOUNT(DECODE_TABLE), opcode_index, &lock_prefix, &seg_reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Execute the assembly
|
// NOTE: Execute the assembly
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
for (size_t opcode_index = 0; opcode_index < opcode_size; opcode_index++) {
|
for (S86_Opcode *prev_opcode = NULL, *opcode = NULL;
|
||||||
S86_Opcode *opcode = opcode_array + opcode_index;
|
register_file.instruction_ptr < buffer.size;
|
||||||
S86_PrintOpcode(*opcode);
|
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)
|
if (opcode->mnemonic == S86_Mnemonic_LOCK || opcode->mnemonic == S86_Mnemonic_SEGMENT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1254,6 +1297,7 @@ int main(int argc, char **argv)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Simulate instruction ==============================================================
|
||||||
S86_RegisterFileFlags prev_flags = register_file.flags;
|
S86_RegisterFileFlags prev_flags = register_file.flags;
|
||||||
switch (opcode->mnemonic) {
|
switch (opcode->mnemonic) {
|
||||||
case S86_Mnemonic_PUSH: /*FALLTHRU*/
|
case S86_Mnemonic_PUSH: /*FALLTHRU*/
|
||||||
@ -1310,7 +1354,6 @@ int main(int argc, char **argv)
|
|||||||
case S86_Mnemonic_JP_JPE: /*FALLTHRU*/
|
case S86_Mnemonic_JP_JPE: /*FALLTHRU*/
|
||||||
case S86_Mnemonic_JO: /*FALLTHRU*/
|
case S86_Mnemonic_JO: /*FALLTHRU*/
|
||||||
case S86_Mnemonic_JS: /*FALLTHRU*/
|
case S86_Mnemonic_JS: /*FALLTHRU*/
|
||||||
case S86_Mnemonic_JNE_JNZ: /*FALLTHRU*/
|
|
||||||
case S86_Mnemonic_JNL_JGE: /*FALLTHRU*/
|
case S86_Mnemonic_JNL_JGE: /*FALLTHRU*/
|
||||||
case S86_Mnemonic_JNLE_JG: /*FALLTHRU*/
|
case S86_Mnemonic_JNLE_JG: /*FALLTHRU*/
|
||||||
case S86_Mnemonic_JNB_JAE: /*FALLTHRU*/
|
case S86_Mnemonic_JNB_JAE: /*FALLTHRU*/
|
||||||
@ -1488,14 +1531,20 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} 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)
|
if (log_instruction_ptr)
|
||||||
S86_PrintFmt("ip:0x%x->0x%x ", register_file.instruction_ptr, register_file.instruction_ptr + opcode->byte_size);
|
S86_PrintFmt("ip:0x%x->0x%x ", opcode->instruction_ptr, register_file.instruction_ptr);
|
||||||
register_file.instruction_ptr += opcode->byte_size;
|
|
||||||
|
|
||||||
// NOTE: Print Flags
|
// NOTE: Flags
|
||||||
if (!S86_RegisterFileFlagsEq(register_file.flags, prev_flags)) {
|
if (!S86_RegisterFileFlagsEq(register_file.flags, prev_flags)) {
|
||||||
S86_PrintFmt("flags:");
|
S86_PrintFmt("flags:");
|
||||||
if (prev_flags.carry)
|
if (prev_flags.carry)
|
||||||
|
@ -323,6 +323,8 @@ typedef enum S86_WidePrefix {
|
|||||||
|
|
||||||
typedef struct S86_Opcode {
|
typedef struct S86_Opcode {
|
||||||
uint8_t byte_size; ///< Number of bytes used to encode this 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_Mnemonic mnemonic; ///< Mnemonic type
|
||||||
S86_EffectiveAddress effective_addr; ///< Src/dest op is an effective address calculation
|
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
|
bool effective_addr_loads_mem; ///< Effective address uses '[]' notation to load address memory
|
||||||
|
BIN
project.rdbg
BIN
project.rdbg
Binary file not shown.
Loading…
Reference in New Issue
Block a user