Completed add, sub, cmp and jump simulations
This commit is contained in:
parent
43c748e0c5
commit
c320371432
8
8086_sim/.gitignore
vendored
Normal file
8
8086_sim/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
listing_0043_immediate_movs
|
||||||
|
listing_0044_register_movs
|
||||||
|
listing_0045_challenge_register_movs
|
||||||
|
listing_0046_add_sub_cmp
|
||||||
|
listing_0047_challenge_flags
|
||||||
|
listing_0048_ip_register
|
||||||
|
listing_0049_conditional_jumps
|
||||||
|
listing_0050_challenge_jumps
|
57
8086_sim/flag_access.cpp
Normal file
57
8086_sim/flag_access.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "include/flag_access.h"
|
||||||
|
#include "include/aliases.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
const char *get_flag_string(flag_access flag);
|
||||||
|
|
||||||
|
static bool flags[FLAG_COUNT] = {false};
|
||||||
|
|
||||||
|
bool get_flag(flag_access flag) {
|
||||||
|
if (flag < FLAG_COUNT) {
|
||||||
|
return flags[flag];
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_flags(u16 value) {
|
||||||
|
if (value == 0) {
|
||||||
|
flags[FLAG_ZERO] = true;
|
||||||
|
flags[FLAG_SIGN] = false;
|
||||||
|
} else if ((value & 0x8000) == 0x8000) {
|
||||||
|
flags[FLAG_ZERO] = false;
|
||||||
|
flags[FLAG_SIGN] = true;
|
||||||
|
} else {
|
||||||
|
flags[FLAG_ZERO] = false;
|
||||||
|
flags[FLAG_SIGN] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_flags() {
|
||||||
|
printf("\t");
|
||||||
|
|
||||||
|
for (u32 i = 0; i < FLAG_COUNT; ++i) {
|
||||||
|
if (flags[i]) {
|
||||||
|
printf("%s", get_flag_string((flag_access)i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get_flag_string(flag_access flag) {
|
||||||
|
const char *output = "";
|
||||||
|
|
||||||
|
switch (flag) {
|
||||||
|
case FLAG_ZERO:
|
||||||
|
output = "Z";
|
||||||
|
break;
|
||||||
|
case FLAG_SIGN:
|
||||||
|
output = "S";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
17
8086_sim/include/flag_access.h
Normal file
17
8086_sim/include/flag_access.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef FLAG_ACCESS_H
|
||||||
|
#define FLAG_ACCESS_H
|
||||||
|
|
||||||
|
#include "aliases.h"
|
||||||
|
|
||||||
|
enum flag_access : u8 {
|
||||||
|
FLAG_ZERO,
|
||||||
|
FLAG_SIGN,
|
||||||
|
|
||||||
|
FLAG_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
bool get_flag(flag_access flag);
|
||||||
|
void set_flags(u16 value);
|
||||||
|
void print_flags();
|
||||||
|
|
||||||
|
#endif // !FLAG_ACCESS_H
|
28
8086_sim/listing_0046_add_sub_cmp.asm
Normal file
28
8086_sim/listing_0046_add_sub_cmp.asm
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
; ========================================================================
|
||||||
|
;
|
||||||
|
; (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 46
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
bits 16
|
||||||
|
|
||||||
|
mov bx, -4093
|
||||||
|
mov cx, 3841
|
||||||
|
sub bx, cx
|
||||||
|
|
||||||
|
mov sp, 998
|
||||||
|
mov bp, 999
|
||||||
|
cmp bp, sp
|
||||||
|
|
||||||
|
add bp, 1027
|
||||||
|
sub bp, 2026
|
36
8086_sim/listing_0047_challenge_flags.asm
Normal file
36
8086_sim/listing_0047_challenge_flags.asm
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
; ========================================================================
|
||||||
|
;
|
||||||
|
; (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 47
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
bits 16
|
||||||
|
|
||||||
|
add bx, 30000
|
||||||
|
add bx, 10000
|
||||||
|
sub bx, 5000
|
||||||
|
sub bx, 5000
|
||||||
|
|
||||||
|
mov bx, 1
|
||||||
|
mov cx, 100
|
||||||
|
add bx, cx
|
||||||
|
|
||||||
|
mov dx, 10
|
||||||
|
sub cx, dx
|
||||||
|
|
||||||
|
add bx, 40000
|
||||||
|
add cx, -90
|
||||||
|
|
||||||
|
mov sp, 99
|
||||||
|
mov bp, 98
|
||||||
|
cmp bp, sp
|
23
8086_sim/listing_0048_ip_register.asm
Normal file
23
8086_sim/listing_0048_ip_register.asm
Normal 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
|
24
8086_sim/listing_0049_conditional_jumps.asm
Normal file
24
8086_sim/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
|
38
8086_sim/listing_0050_challenge_jumps.asm
Normal file
38
8086_sim/listing_0050_challenge_jumps.asm
Normal file
@ -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
|
BIN
8086_sim/sim86
Executable file
BIN
8086_sim/sim86
Executable file
Binary file not shown.
@ -1,11 +1,18 @@
|
|||||||
#include "include/aliases.h"
|
#include "include/aliases.h"
|
||||||
|
#include "include/flag_access.h"
|
||||||
#include "include/reg_access.h"
|
#include "include/reg_access.h"
|
||||||
#include "include/sim86_lib.h"
|
#include "include/sim86_lib.h"
|
||||||
#include <bits/types/FILE.h>
|
#include <bits/types/FILE.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void decode_operand(instruction_operand operand);
|
struct basic_string {
|
||||||
|
char str[4096];
|
||||||
|
};
|
||||||
|
|
||||||
|
u16 get_operand_value(instruction_operand operand);
|
||||||
|
basic_string get_operand_string(instruction_operand operand);
|
||||||
|
void print_instruction(instruction inst);
|
||||||
void mov_to_register(const register_access ®,
|
void mov_to_register(const register_access ®,
|
||||||
const instruction_operand &source);
|
const instruction_operand &source);
|
||||||
|
|
||||||
@ -44,6 +51,8 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
bool accessed_registers[REGISTER_COUNT] = {false};
|
bool accessed_registers[REGISTER_COUNT] = {false};
|
||||||
|
|
||||||
|
printf("\nDisassembly:\n");
|
||||||
|
|
||||||
while (offset < size) {
|
while (offset < size) {
|
||||||
instruction decoded;
|
instruction decoded;
|
||||||
Sim86_Decode8086Instruction(size - offset, buffer + offset, &decoded);
|
Sim86_Decode8086Instruction(size - offset, buffer + offset, &decoded);
|
||||||
@ -51,46 +60,129 @@ int main(int argc, char *argv[]) {
|
|||||||
if (decoded.Op) {
|
if (decoded.Op) {
|
||||||
offset += decoded.Size;
|
offset += decoded.Size;
|
||||||
|
|
||||||
if (decoded.Op == Op_mov) {
|
print_instruction(decoded);
|
||||||
instruction_operand dest = decoded.Operands[0];
|
|
||||||
instruction_operand source = decoded.Operands[1];
|
instruction_operand dest = decoded.Operands[0];
|
||||||
|
instruction_operand source = decoded.Operands[1];
|
||||||
|
|
||||||
|
switch (decoded.Op) {
|
||||||
|
case Op_mov: {
|
||||||
|
|
||||||
if (dest.Type == Operand_Register) {
|
if (dest.Type == Operand_Register) {
|
||||||
mov_to_register(dest.Register, source);
|
mov_to_register(dest.Register, source);
|
||||||
|
|
||||||
accessed_registers[dest.Register.Index] = true;
|
accessed_registers[dest.Register.Index] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op_add: {
|
||||||
|
if (dest.Type == Operand_Register) {
|
||||||
|
u16 value = get_register(dest.Register);
|
||||||
|
|
||||||
|
value += get_operand_value(source);
|
||||||
|
set_flags(value);
|
||||||
|
|
||||||
|
set_register(dest.Register, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op_sub:
|
||||||
|
case Op_cmp: {
|
||||||
|
if (dest.Type == Operand_Register) {
|
||||||
|
u16 value = get_register(dest.Register);
|
||||||
|
|
||||||
|
value -= get_operand_value(source);
|
||||||
|
set_flags(value);
|
||||||
|
|
||||||
|
if (decoded.Op == Op_sub) {
|
||||||
|
set_register(dest.Register, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op_jne: {
|
||||||
|
if (!get_flag(FLAG_ZERO)) {
|
||||||
|
i16 inst_offset = get_operand_value(dest);
|
||||||
|
|
||||||
|
offset += inst_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("\nFinal registers:\n");
|
||||||
|
|
||||||
for (u32 i = 0; i < REGISTER_COUNT; ++i) {
|
for (u32 i = 0; i < REGISTER_COUNT; ++i) {
|
||||||
if (accessed_registers[i]) {
|
if (accessed_registers[i]) {
|
||||||
register_access reg = {i, 0, 2};
|
register_access reg = {i, 0, 2};
|
||||||
u16 value = get_register(reg);
|
u16 value = get_register(reg);
|
||||||
|
|
||||||
printf("%s: 0x%04x (%d)\n", get_register_name(reg), value, value);
|
printf("\t%s: 0x%04x (%d)\n", get_register_name(reg), value, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print the instruction pointer register
|
||||||
|
printf("\tip: 0x%04x (%d)\n", offset, offset);
|
||||||
|
|
||||||
|
printf("\nFinal flags:\n");
|
||||||
|
print_flags();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_operand(instruction_operand operand) {
|
u16 get_operand_value(instruction_operand operand) {
|
||||||
switch (operand.Type) {
|
switch (operand.Type) {
|
||||||
case Operand_Register:
|
case Operand_Register:
|
||||||
printf("Register operand: %d, %d, %d\n", operand.Register.Index,
|
return get_register(operand.Register);
|
||||||
operand.Register.Offset, operand.Register.Count);
|
|
||||||
break;
|
break;
|
||||||
case Operand_Memory:
|
case Operand_Memory:
|
||||||
// printf("Memory operand\n");
|
return 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case Operand_Immediate:
|
case Operand_Immediate:
|
||||||
// printf("Immediate operand\n");
|
return operand.Immediate.Value;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_string get_operand_string(instruction_operand operand) {
|
||||||
|
basic_string output = {""};
|
||||||
|
|
||||||
|
switch (operand.Type) {
|
||||||
|
case Operand_Register:
|
||||||
|
sprintf(output.str, "%s", get_register_name(operand.Register));
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Operand_Memory:
|
||||||
|
sprintf(output.str, "%s", "MEM OPERAND");
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Operand_Immediate:
|
||||||
|
sprintf(output.str, "%d", operand.Immediate.Value);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_instruction(instruction inst) {
|
||||||
|
printf("\t%s %s, %s\n", Sim86_MnemonicFromOperationType(inst.Op),
|
||||||
|
get_operand_string(inst.Operands[0]).str,
|
||||||
|
get_operand_string(inst.Operands[1]).str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mov_to_register(const register_access ®,
|
void mov_to_register(const register_access ®,
|
||||||
|
Loading…
Reference in New Issue
Block a user