Completed homework for 8086 simulator

This commit is contained in:
Abdelrahman Said 2023-04-16 14:29:54 -07:00
parent 60538301d5
commit 2900e508a1
6 changed files with 330 additions and 25 deletions

7
8086_sim/.gitignore vendored
View File

@ -7,3 +7,10 @@ listing_0047_challenge_flags
listing_0048_ip_register listing_0048_ip_register
listing_0049_conditional_jumps listing_0049_conditional_jumps
listing_0050_challenge_jumps listing_0050_challenge_jumps
listing_0051_memory_mov
listing_0052_memory_add_loop
listing_0053_add_loop_challenge
listing_0054_draw_rectangle
test.asm
test
image.data

View File

@ -0,0 +1,30 @@
; ========================================================================
;
; (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 51
; ========================================================================
bits 16
mov word [1000], 1
mov word [1002], 2
mov word [1004], 3
mov word [1006], 4
mov bx, 1000
mov word [bx + 4], 10
mov bx, word [1000]
mov cx, word [1002]
mov dx, word [1004]
mov bp, word [1006]

View 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 52
; ========================================================================
bits 16
mov dx, 6
mov bp, 1000
mov si, 0
init_loop_start:
mov word [bp + si], si
add si, 2
cmp si, dx
jnz init_loop_start
mov bx, 0
mov si, 0
add_loop_start:
mov cx, word [bp + si]
add bx, cx
add si, 2
cmp si, dx
jnz add_loop_start

View File

@ -0,0 +1,35 @@
; ========================================================================
;
; (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 53
; ========================================================================
bits 16
mov dx, 6
mov bp, 1000
mov si, 0
init_loop_start:
mov word [bp + si], si
add si, 2
cmp si, dx
jnz init_loop_start
mov bx, 0
mov si, dx
sub bp, 2
add_loop_start:
add bx, word [bp + si]
sub si, 2
jnz add_loop_start

View File

@ -0,0 +1,43 @@
; ========================================================================
;
; (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 54
; ========================================================================
bits 16
; Start image after one row, to avoid overwriting our code!
mov bp, 64*4
mov dx, 0
y_loop_start:
mov cx, 0
x_loop_start:
; Fill pixel
mov word [bp + 0], cx ; Red
mov word [bp + 2], dx ; Blue
mov byte [bp + 3], 255 ; Alpha
; Advance pixel location
add bp, 4
; Advance X coordinate and loop
add cx, 1
cmp cx, 64
jnz x_loop_start
; Advance Y coordinate and loop
add dx, 1
cmp dx, 64
jnz y_loop_start

View File

@ -1,22 +1,43 @@
#include "include/aliases.h" #include "include/aliases.h"
#include "include/flag_access.h" #include "include/flag_access.h"
#include "include/reg_access.h" #include "include/reg_access.h"
#include "include/sim86_instruction.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>
#define MEM_SIZE (1 << 16) #define MEM_SIZE (1 << 16)
#define BITS_PER_BYTE 8
struct basic_string { struct basic_string {
char str[4096]; char str[4096];
}; };
u16 get_operand_value(instruction_operand operand); struct membuf {
basic_string get_operand_string(instruction_operand operand); u8 buffer[MEM_SIZE];
u64 mem_start;
};
struct mem_access_result {
u16 value;
u32 error;
};
u16 get_operand_value(instruction_operand operand, bool wide);
basic_string get_operand_string(instruction_operand operand, bool wide);
void print_instruction(instruction inst); void print_instruction(instruction inst);
void mov_to_register(const register_access &reg, void mov_to_register(const register_access &reg,
const instruction_operand &source); const instruction_operand &source, bool wide);
void mov_to_memory(const effective_address_expression &addrexp,
const instruction_operand &source, bool wide);
mem_access_result get_mem_value(const effective_address_expression &addrexp,
bool wide);
mem_access_result set_mem_value(const effective_address_expression &addrexp,
u16 value, bool wide);
u16 get_mem_index(const effective_address_expression &addrexp);
static membuf memory;
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc < 2) { if (argc < 2) {
@ -24,8 +45,8 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
u8 memory[MEM_SIZE]; memset((void *)memory.buffer, 0, MEM_SIZE);
memset((void *)memory, 0, MEM_SIZE); memory.mem_start = 0;
const char *filename = argv[1]; const char *filename = argv[1];
@ -42,14 +63,14 @@ int main(int argc, char *argv[]) {
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
fread((void *)memory, sizeof(u8), size, fp); fread((void *)memory.buffer, sizeof(u8), size, fp);
memory.mem_start = size + 1;
fclose(fp); fclose(fp);
instruction_table table; instruction_table table;
Sim86_Get8086InstructionTable(&table); Sim86_Get8086InstructionTable(&table);
u32 mem_start = size + 1;
u32 offset = 0; u32 offset = 0;
bool accessed_registers[REGISTER_COUNT] = {false}; bool accessed_registers[REGISTER_COUNT] = {false};
@ -58,10 +79,12 @@ int main(int argc, char *argv[]) {
while (offset < size) { while (offset < size) {
instruction decoded; instruction decoded;
Sim86_Decode8086Instruction(size - offset, memory + offset, &decoded); Sim86_Decode8086Instruction(size - offset, memory.buffer + offset,
&decoded);
if (decoded.Op) { if (decoded.Op) {
offset += decoded.Size; offset += decoded.Size;
bool wide = (decoded.Flags & Inst_Wide) == Inst_Wide;
print_instruction(decoded); print_instruction(decoded);
@ -70,11 +93,12 @@ int main(int argc, char *argv[]) {
switch (decoded.Op) { switch (decoded.Op) {
case Op_mov: { 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, wide);
accessed_registers[dest.Register.Index] = true; accessed_registers[dest.Register.Index] = true;
} else if (dest.Type == Operand_Memory) {
mov_to_memory(dest.Address, source, wide);
} }
break; break;
@ -83,7 +107,7 @@ int main(int argc, char *argv[]) {
if (dest.Type == Operand_Register) { if (dest.Type == Operand_Register) {
u16 value = get_register(dest.Register); u16 value = get_register(dest.Register);
value += get_operand_value(source); value += get_operand_value(source, wide);
set_flags(value); set_flags(value);
set_register(dest.Register, value); set_register(dest.Register, value);
@ -96,7 +120,7 @@ int main(int argc, char *argv[]) {
if (dest.Type == Operand_Register) { if (dest.Type == Operand_Register) {
u16 value = get_register(dest.Register); u16 value = get_register(dest.Register);
value -= get_operand_value(source); value -= get_operand_value(source, wide);
set_flags(value); set_flags(value);
if (decoded.Op == Op_sub) { if (decoded.Op == Op_sub) {
@ -108,7 +132,7 @@ int main(int argc, char *argv[]) {
} }
case Op_jne: { case Op_jne: {
if (!get_flag(FLAG_ZERO)) { if (!get_flag(FLAG_ZERO)) {
i16 inst_offset = get_operand_value(dest); i16 inst_offset = get_operand_value(dest, wide);
offset += inst_offset; offset += inst_offset;
} }
@ -136,30 +160,54 @@ int main(int argc, char *argv[]) {
printf("\nFinal flags:\n"); printf("\nFinal flags:\n");
print_flags(); print_flags();
#if 0 // Only needed (and working) for listing 0054
#define SIZE 64
#define BYTES SIZE * 4 * SIZE
u8 image[BYTES];
mempcpy(image, &(memory.buffer[memory.mem_start + (SIZE * 4)]), BYTES);
FILE *out = fopen("image.data", "wb");
fwrite(image, sizeof(u8), BYTES, out);
fclose(out);
#endif
return 0; return 0;
} }
u16 get_operand_value(instruction_operand operand) { u16 get_operand_value(instruction_operand operand, bool wide) {
u16 output = 0;
switch (operand.Type) { switch (operand.Type) {
case Operand_Register: case Operand_Register:
return get_register(operand.Register); output = get_register(operand.Register);
break; break;
case Operand_Memory: case Operand_Memory: {
return 0; mem_access_result result = get_mem_value(operand.Address, wide);
if (result.error) {
break;
}
output = result.value;
break; break;
}
case Operand_Immediate: case Operand_Immediate:
return operand.Immediate.Value; output = operand.Immediate.Value;
break; break;
default: default:
return 0;
break; break;
} }
return output;
} }
basic_string get_operand_string(instruction_operand operand) { basic_string get_operand_string(instruction_operand operand, bool wide) {
basic_string output = {""}; basic_string output = {""};
switch (operand.Type) { switch (operand.Type) {
@ -167,10 +215,27 @@ basic_string get_operand_string(instruction_operand operand) {
sprintf(output.str, "%s", get_register_name(operand.Register)); sprintf(output.str, "%s", get_register_name(operand.Register));
break; break;
case Operand_Memory: case Operand_Memory: {
sprintf(output.str, "%s", "MEM OPERAND"); char mem_string[1024] = {0};
register_access reg1 = operand.Address.Terms[0].Register;
if (reg1.Index != 0) {
sprintf(mem_string, "%s + ", get_register_name(reg1));
}
register_access reg2 = operand.Address.Terms[1].Register;
if (reg2.Index != 0) {
strcat(mem_string, get_register_name(reg2));
} else {
u32 length = strlen(mem_string);
sprintf(&(mem_string[length]), "%d", operand.Address.Displacement);
}
sprintf(output.str, "%s [%s]", wide ? "word" : "byte", mem_string);
break; break;
}
case Operand_Immediate: case Operand_Immediate:
sprintf(output.str, "%d", operand.Immediate.Value); sprintf(output.str, "%d", operand.Immediate.Value);
@ -183,13 +248,15 @@ basic_string get_operand_string(instruction_operand operand) {
} }
void print_instruction(instruction inst) { void print_instruction(instruction inst) {
bool wide = (inst.Flags & Inst_Wide) == Inst_Wide;
printf("\t%s %s, %s\n", Sim86_MnemonicFromOperationType(inst.Op), printf("\t%s %s, %s\n", Sim86_MnemonicFromOperationType(inst.Op),
get_operand_string(inst.Operands[0]).str, get_operand_string(inst.Operands[0], wide).str,
get_operand_string(inst.Operands[1]).str); get_operand_string(inst.Operands[1], wide).str);
} }
void mov_to_register(const register_access &reg, void mov_to_register(const register_access &reg,
const instruction_operand &source) { const instruction_operand &source, bool wide) {
switch (source.Type) { switch (source.Type) {
case Operand_Immediate: case Operand_Immediate:
set_register(reg, source.Immediate.Value); set_register(reg, source.Immediate.Value);
@ -197,7 +264,94 @@ void mov_to_register(const register_access &reg,
case Operand_Register: case Operand_Register:
set_register(reg, get_register(source.Register)); set_register(reg, get_register(source.Register));
break; break;
case Operand_Memory: {
mem_access_result result = get_mem_value(source.Address, wide);
if (!result.error) {
set_register(reg, result.value);
}
break;
}
default: default:
break; break;
} }
} }
void mov_to_memory(const effective_address_expression &addrexp,
const instruction_operand &source, bool wide) {
switch (source.Type) {
case Operand_Immediate:
set_mem_value(addrexp, source.Immediate.Value, wide);
break;
case Operand_Register:
set_mem_value(addrexp, get_register(source.Register), wide);
break;
case Operand_Memory: {
mem_access_result result = get_mem_value(source.Address, wide);
if (!result.error) {
set_mem_value(addrexp, result.value, wide);
}
break;
}
default:
break;
}
}
mem_access_result get_mem_value(const effective_address_expression &addrexp,
bool wide) {
u16 index = get_mem_index(addrexp);
mem_access_result result = {0, 0};
if (memory.mem_start + index >= MEM_SIZE) {
result.error = 1;
} else {
result.value |= memory.buffer[memory.mem_start + index];
if (wide) {
result.value |= (memory.buffer[memory.mem_start + index + 1]
<< (wide ? BITS_PER_BYTE : 0));
}
}
return result;
}
mem_access_result set_mem_value(const effective_address_expression &addrexp,
u16 value, bool wide) {
u16 index = get_mem_index(addrexp);
mem_access_result result = {0, 0};
if (memory.mem_start + index >= MEM_SIZE) {
result.error = 1;
} else {
memory.buffer[memory.mem_start + index] = (u8)value;
if (wide) {
memory.buffer[memory.mem_start + index + 1] =
(u8)(value >> (wide ? BITS_PER_BYTE : 0));
}
result.value = value;
}
return result;
}
u16 get_mem_index(const effective_address_expression &addrexp) {
u16 index = addrexp.Displacement;
const u16 term_count = 2;
for (u16 i = 0; i < term_count; ++i) {
if (addrexp.Terms[i].Register.Index != 0) {
index += get_register(addrexp.Terms[i].Register);
}
}
return index;
}