diff --git a/asm_files/list-0050.asm b/asm_files/list-0050.asm new file mode 100644 index 0000000..8d2f484 --- /dev/null +++ b/asm_files/list-0050.asm @@ -0,0 +1,38 @@ +; ======================================================================== +; +; (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 50 +; ======================================================================== + +bits 16 + +mov ax, 10 +mov bx, 10 +mov cx, 10 + +label_0: +cmp bx, cx +je label_1 + +add ax, 1 +jp label_2 + +label_1: +sub bx, 5 +jb label_3 + +label_2: +sub cx, 2 + +label_3: +loopnz label_0 diff --git a/asm_files/list-0050.txt b/asm_files/list-0050.txt new file mode 100644 index 0000000..d908b03 --- /dev/null +++ b/asm_files/list-0050.txt @@ -0,0 +1,37 @@ +--- test\listing_0050_challenge_jumps execution --- +mov ax, 10 ; ax:0x0->0xa ip:0x0->0x3 +mov bx, 10 ; bx:0x0->0xa ip:0x3->0x6 +mov cx, 10 ; cx:0x0->0xa ip:0x6->0x9 +cmp bx, cx ; ip:0x9->0xb flags:->PZ +je $+7 ; ip:0xb->0x12 +sub bx, 5 ; bx:0xa->0x5 ip:0x12->0x15 flags:PZ->P +jb $+5 ; ip:0x15->0x17 +sub cx, 2 ; cx:0xa->0x8 ip:0x17->0x1a flags:P-> +loopnz $-17 ; cx:0x8->0x7 ip:0x1a->0x9 +cmp bx, cx ; ip:0x9->0xb flags:->CAS +je $+7 ; ip:0xb->0xd +add ax, 1 ; ax:0xa->0xb ip:0xd->0x10 flags:CAS-> +jp $+7 ; ip:0x10->0x12 +sub bx, 5 ; bx:0x5->0x0 ip:0x12->0x15 flags:->PZ +jb $+5 ; ip:0x15->0x17 +sub cx, 2 ; cx:0x7->0x5 ip:0x17->0x1a flags:PZ->P +loopnz $-17 ; cx:0x5->0x4 ip:0x1a->0x9 +cmp bx, cx ; ip:0x9->0xb flags:P->CPAS +je $+7 ; ip:0xb->0xd +add ax, 1 ; ax:0xb->0xc ip:0xd->0x10 flags:CPAS->P +jp $+7 ; ip:0x10->0x17 +sub cx, 2 ; cx:0x4->0x2 ip:0x17->0x1a flags:P-> +loopnz $-17 ; cx:0x2->0x1 ip:0x1a->0x9 +cmp bx, cx ; ip:0x9->0xb flags:->CPAS +je $+7 ; ip:0xb->0xd +add ax, 1 ; ax:0xc->0xd ip:0xd->0x10 flags:CPAS-> +jp $+7 ; ip:0x10->0x12 +sub bx, 5 ; bx:0x0->0xfffb ip:0x12->0x15 flags:->CAS +jb $+5 ; ip:0x15->0x1a +loopnz $-17 ; cx:0x1->0x0 ip:0x1a->0x1c + +Final registers: + ax: 0x000d (13) + bx: 0xfffb (65531) + ip: 0x001c (28) + flags: CAS diff --git a/execution.odin b/execution.odin index 261cc14..027369b 100644 --- a/execution.odin +++ b/execution.odin @@ -108,25 +108,33 @@ execute_instruction :: proc(cpu: ^Cpu, inst: Instruction) { check_carry_flag(cpu, dst_val, src_val, false) } } else if jmp_offset,ok := inst.src.(Jump); ok { + jump: bool #partial switch inst.opname { - case .JNZ, .JNE: - if !cpu.flags[.ZF] { - cpu.registers[.ip].full += i16(jmp_offset) - if jmp_offset < 0 { - cpu.registers[.ip].full -= i16(inst.bytes_read) - } - } + case .JNZ, .JNE: jump = !cpu.flags[.ZF] + case .JE, .JZ: jump = cpu.flags[.ZF] + case .JP, .JPE: jump = cpu.flags[.PF] + case .JB, .JNAE: jump = cpu.flags[.CF] + + case .LOOPNZ, .LOOPNE: + cpu.registers[.cx].full -= 1 + // According to this resource, the loopnz inst does not change any flags + // https://yassinebridi.github.io/asm-docs/8086_instruction_set.html#LOOPNZ + // check_zero_flag(cpu, cpu.registers[.cx].full) + jump = cpu.registers[.cx].full != 0 && !cpu.flags[.ZF] + } + if jump { + cpu.registers[.ip].full += i16(jmp_offset) + cpu.registers[.ip].full -= i16(inst.bytes_read) } } } execute_instructions :: proc(cpu: ^Cpu, instructions: DecodedInstructions) { halt := false - fmt.println(instructions.total_bytes_decoded) for !halt && get_ip(cpu) < instructions.total_bytes_decoded { inst,ok := instructions.inst_map[get_ip(cpu)] if !ok { - // Something went wrong with a jump, most likely + panic("Something went wrong with a jump, most likely") } cpu.registers[.ip].full += i16(inst.bytes_read) execute_instruction(cpu, inst) diff --git a/instructions.odin b/instructions.odin index 09b89dc..d0685cc 100644 --- a/instructions.odin +++ b/instructions.odin @@ -106,6 +106,7 @@ Op :: enum { LOOP, LOOPZ, LOOPNZ, + LOOPNE, JCXZ, } diff --git a/sim8086.odin b/sim8086.odin index 2592a25..2cc0403 100644 --- a/sim8086.odin +++ b/sim8086.odin @@ -44,7 +44,7 @@ main :: proc() { } cpu := Cpu { - memory = make([dynamic]u8, 65536), + memory = make([dynamic]u8, 1_048_576), // Exact num per the manual } execute_instructions(&cpu, decoded_insts)