diff --git a/examples/48_ip_register.asm b/examples/48_ip_register.asm new file mode 100644 index 0000000..6c2e237 --- /dev/null +++ b/examples/48_ip_register.asm @@ -0,0 +1,23 @@ +; ======================================================================== +; +; (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 48 +; ======================================================================== + +bits 16 + +mov cx, 200 +mov bx, cx +add cx, 1000 +mov bx, 2000 +sub cx, bx \ No newline at end of file diff --git a/examples/48_ip_register.txt b/examples/48_ip_register.txt new file mode 100644 index 0000000..0ba797e --- /dev/null +++ b/examples/48_ip_register.txt @@ -0,0 +1,12 @@ +--- test\listing_0048_ip_register execution --- +mov cx, 200 ; cx:0x0->0xc8 ip:0x0->0x3 +mov bx, cx ; bx:0x0->0xc8 ip:0x3->0x5 +add cx, 1000 ; cx:0xc8->0x4b0 ip:0x5->0x9 flags:->A +mov bx, 2000 ; bx:0xc8->0x7d0 ip:0x9->0xc +sub cx, bx ; cx:0x4b0->0xfce0 ip:0xc->0xe flags:A->CS + +Final registers: + bx: 0x07d0 (2000) + cx: 0xfce0 (64736) + ip: 0x000e (14) + flags: CS diff --git a/examples/49_conditional_jumps.asm b/examples/49_conditional_jumps.asm new file mode 100644 index 0000000..309db87 --- /dev/null +++ b/examples/49_conditional_jumps.asm @@ -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 \ No newline at end of file diff --git a/examples/49_conditional_jumps.txt b/examples/49_conditional_jumps.txt new file mode 100644 index 0000000..ae1fae6 --- /dev/null +++ b/examples/49_conditional_jumps.txt @@ -0,0 +1,17 @@ +--- 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 diff --git a/src/main.c b/src/main.c index e81d83b..21e7ac2 100644 --- a/src/main.c +++ b/src/main.c @@ -87,7 +87,7 @@ err: int dissassemble(FILE *src, FILE *dst) { fprintf(dst, "bits 16\n\n"); - struct memory mem = { .mem = { 0xFF } }; + struct memory mem = { 0 }; int byte_count = load_mem_from_stream(&mem, src, 0); if (byte_count == -1) { fprintf(stderr, "ERROR: Failed to load file to memory\n"); @@ -96,7 +96,7 @@ int dissassemble(FILE *src, FILE *dst) { char buff[256]; struct instruction inst; - u32 inst_address = 0; + u16 inst_address = 0; while (inst_address < byte_count) { enum decode_error err = decode_instruction(&mem, &inst_address, &inst); if (err == DECODE_ERR_EOF) break; @@ -114,7 +114,7 @@ int dissassemble(FILE *src, FILE *dst) { } int simulate(FILE *src) { - struct memory mem; + struct memory mem = { 0 }; int byte_count = load_mem_from_stream(&mem, src, 0); if (byte_count == -1) { fprintf(stderr, "ERROR: Failed to load file to memory\n"); @@ -123,12 +123,11 @@ int simulate(FILE *src) { struct cpu_state state = { 0 }; struct instruction inst; - u32 inst_address = 0; - while (inst_address < byte_count) { - enum decode_error err = decode_instruction(&mem, &inst_address, &inst); + while (state.ip < byte_count) { + enum decode_error err = decode_instruction(&mem, &state.ip, &inst); if (err == DECODE_ERR_EOF) break; if (err != DECODE_OK) { - fprintf(stderr, "ERROR: Failed to decode instruction at 0x%08x: %s\n", inst_address, decode_error_to_str(err)); + fprintf(stderr, "ERROR: Failed to decode instruction at 0x%08x: %s\n", state.ip, decode_error_to_str(err)); return -1; } execute_instruction(&state, &inst); @@ -142,6 +141,7 @@ int simulate(FILE *src) { printf(" bp: 0x%04x (%d)\n", state.bp, state.bp); printf(" si: 0x%04x (%d)\n", state.si, state.si); printf(" di: 0x%04x (%d)\n", state.di, state.di); + printf(" ip: 0x%04x (%d)\n", state.ip, state.ip); printf(" flags: %s%s\n", state.flags.sign ? "S" : "", state.flags.zero ? "Z" : ""); return 0; } diff --git a/src/sim8086.h b/src/sim8086.h index debb120..e502c59 100644 --- a/src/sim8086.h +++ b/src/sim8086.h @@ -12,7 +12,7 @@ #define panic(...) fprintf(stderr, "PANIC(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort() #define todo(...) fprintf(stderr, "TODO(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort() #define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) -#define MEMORY_SIZE (1024 * 1024) // 1 MiB +#define MEMORY_SIZE 65536 // 2^16 enum operation { OP_MOV, @@ -121,4 +121,6 @@ struct cpu_state { bool sign; // TODO: Add all flags } flags; + + u16 ip; }; \ No newline at end of file diff --git a/src/sim8086_decoder.c b/src/sim8086_decoder.c index 05d3347..283d312 100644 --- a/src/sim8086_decoder.c +++ b/src/sim8086_decoder.c @@ -74,7 +74,7 @@ static enum mem_base decode_mem_base(u8 rm) { static void decode_reg_or_mem( struct reg_or_mem_value *value, struct memory *mem, - u32 *addr, + u16 *addr, u8 rm, u8 mod, bool wide @@ -110,7 +110,7 @@ static void decode_reg_or_mem( static void deocde_reg_or_mem_to_src( struct src_value *value, struct memory *mem, - u32 *addr, + u16 *addr, u8 rm, u8 mod, bool wide @@ -129,7 +129,7 @@ static void deocde_reg_or_mem_to_src( // TODO: change to readinf from a byte buffer // TODO: add handling for 'DECODE_ERR_MISSING_BYTES' // Handy reference: Table 4-12. 8086 Instruction Encoding -enum decode_error decode_instruction(struct memory *mem, u32 *addr, struct instruction *output) { +enum decode_error decode_instruction(struct memory *mem, u16 *addr, struct instruction *output) { u8 byte1 = pull_byte_at(mem, addr); // MOVE: Register memory to/from register diff --git a/src/sim8086_memory.c b/src/sim8086_memory.c index be91079..514eb19 100644 --- a/src/sim8086_memory.c +++ b/src/sim8086_memory.c @@ -25,11 +25,11 @@ int load_mem_from_file(struct memory *mem, const char *filename, u32 start) { } // TODO: Make this error some kind of error, when reading past end -u8 read_byte_at(struct memory *mem, u32 address) { +u8 read_byte_at(struct memory *mem, u16 address) { return mem->mem[address % MEMORY_SIZE]; } -u8 pull_byte_at(struct memory *mem, u32 *address) { +u8 pull_byte_at(struct memory *mem, u16 *address) { u8 byte = read_byte_at(mem, *address); (*address)++; return byte; diff --git a/src/sim8086_simulator.c b/src/sim8086_simulator.c index ab99040..db929b4 100644 --- a/src/sim8086_simulator.c +++ b/src/sim8086_simulator.c @@ -196,7 +196,14 @@ void execute_instruction(struct cpu_state *state, struct instruction *inst) { } break; } - default: + case OP_JNE: { + if (!state->flags.zero) { + i8 jmp_offset = inst->jmp_offset; + state->ip += jmp_offset; + } + + break; + } default: todo("Unhandled instruction execution '%s'\n", operation_to_str(inst->op)); } } \ No newline at end of file