1
0

implement conditional jumps

This commit is contained in:
Rokas Puzonas 2023-05-07 14:26:20 +03:00
parent 6238b07cdd
commit 0d7a1beedd
9 changed files with 99 additions and 14 deletions

View File

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

View File

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

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

View File

@ -87,7 +87,7 @@ err:
int dissassemble(FILE *src, FILE *dst) { int dissassemble(FILE *src, FILE *dst) {
fprintf(dst, "bits 16\n\n"); 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); int byte_count = load_mem_from_stream(&mem, src, 0);
if (byte_count == -1) { if (byte_count == -1) {
fprintf(stderr, "ERROR: Failed to load file to memory\n"); fprintf(stderr, "ERROR: Failed to load file to memory\n");
@ -96,7 +96,7 @@ int dissassemble(FILE *src, FILE *dst) {
char buff[256]; char buff[256];
struct instruction inst; struct instruction inst;
u32 inst_address = 0; u16 inst_address = 0;
while (inst_address < byte_count) { while (inst_address < byte_count) {
enum decode_error err = decode_instruction(&mem, &inst_address, &inst); enum decode_error err = decode_instruction(&mem, &inst_address, &inst);
if (err == DECODE_ERR_EOF) break; if (err == DECODE_ERR_EOF) break;
@ -114,7 +114,7 @@ int dissassemble(FILE *src, FILE *dst) {
} }
int simulate(FILE *src) { int simulate(FILE *src) {
struct memory mem; struct memory mem = { 0 };
int byte_count = load_mem_from_stream(&mem, src, 0); int byte_count = load_mem_from_stream(&mem, src, 0);
if (byte_count == -1) { if (byte_count == -1) {
fprintf(stderr, "ERROR: Failed to load file to memory\n"); fprintf(stderr, "ERROR: Failed to load file to memory\n");
@ -123,12 +123,11 @@ int simulate(FILE *src) {
struct cpu_state state = { 0 }; struct cpu_state state = { 0 };
struct instruction inst; struct instruction inst;
u32 inst_address = 0; while (state.ip < byte_count) {
while (inst_address < byte_count) { enum decode_error err = decode_instruction(&mem, &state.ip, &inst);
enum decode_error err = decode_instruction(&mem, &inst_address, &inst);
if (err == DECODE_ERR_EOF) break; if (err == DECODE_ERR_EOF) break;
if (err != DECODE_OK) { 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; return -1;
} }
execute_instruction(&state, &inst); execute_instruction(&state, &inst);
@ -142,6 +141,7 @@ int simulate(FILE *src) {
printf(" bp: 0x%04x (%d)\n", state.bp, state.bp); printf(" bp: 0x%04x (%d)\n", state.bp, state.bp);
printf(" si: 0x%04x (%d)\n", state.si, state.si); printf(" si: 0x%04x (%d)\n", state.si, state.si);
printf(" di: 0x%04x (%d)\n", state.di, state.di); 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" : ""); printf(" flags: %s%s\n", state.flags.sign ? "S" : "", state.flags.zero ? "Z" : "");
return 0; return 0;
} }

View File

@ -12,7 +12,7 @@
#define panic(...) fprintf(stderr, "PANIC(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort() #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 todo(...) fprintf(stderr, "TODO(%s:%d): ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); abort()
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) #define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
#define MEMORY_SIZE (1024 * 1024) // 1 MiB #define MEMORY_SIZE 65536 // 2^16
enum operation { enum operation {
OP_MOV, OP_MOV,
@ -121,4 +121,6 @@ struct cpu_state {
bool sign; bool sign;
// TODO: Add all flags // TODO: Add all flags
} flags; } flags;
u16 ip;
}; };

View File

@ -74,7 +74,7 @@ static enum mem_base decode_mem_base(u8 rm) {
static void decode_reg_or_mem( static void decode_reg_or_mem(
struct reg_or_mem_value *value, struct reg_or_mem_value *value,
struct memory *mem, struct memory *mem,
u32 *addr, u16 *addr,
u8 rm, u8 rm,
u8 mod, u8 mod,
bool wide bool wide
@ -110,7 +110,7 @@ static void decode_reg_or_mem(
static void deocde_reg_or_mem_to_src( static void deocde_reg_or_mem_to_src(
struct src_value *value, struct src_value *value,
struct memory *mem, struct memory *mem,
u32 *addr, u16 *addr,
u8 rm, u8 rm,
u8 mod, u8 mod,
bool wide bool wide
@ -129,7 +129,7 @@ static void deocde_reg_or_mem_to_src(
// TODO: change to readinf from a byte buffer // TODO: change to readinf from a byte buffer
// TODO: add handling for 'DECODE_ERR_MISSING_BYTES' // TODO: add handling for 'DECODE_ERR_MISSING_BYTES'
// Handy reference: Table 4-12. 8086 Instruction Encoding // 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); u8 byte1 = pull_byte_at(mem, addr);
// MOVE: Register memory to/from register // MOVE: Register memory to/from register

View File

@ -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 // 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]; 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); u8 byte = read_byte_at(mem, *address);
(*address)++; (*address)++;
return byte; return byte;

View File

@ -196,7 +196,14 @@ void execute_instruction(struct cpu_state *state, struct instruction *inst) {
} }
break; 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)); todo("Unhandled instruction execution '%s'\n", operation_to_str(inst->op));
} }
} }