complete first homework
This commit is contained in:
parent
2f1c0da937
commit
32f7f00952
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
main.exe
|
23
.vscode/c_cpp_properties.json
vendored
Normal file
23
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"C:/MinGW/include/**"
|
||||
],
|
||||
"defines": [
|
||||
"_DEBUG",
|
||||
"UNICODE",
|
||||
"_UNICODE"
|
||||
],
|
||||
"windowsSdkVersion": "10.0.22000.0",
|
||||
"compilerPath": "C:/MinGW/bin/gcc.exe",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++17",
|
||||
"intelliSenseMode": "windows-gcc-x86",
|
||||
"configurationProvider": "ms-vscode.makefile-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
11
.vscode/settings.json
vendored
Normal file
11
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"stdlib.h": "c",
|
||||
"stdio.h": "c",
|
||||
"os.h": "c",
|
||||
"fcntl.h": "c",
|
||||
"io.h": "c",
|
||||
"errno.h": "c",
|
||||
"stdbool.h": "c"
|
||||
}
|
||||
}
|
11
Makefile
Normal file
11
Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
CC=gcc
|
||||
CFLAGS=-g -Wall
|
||||
INCLUDES=./include
|
||||
|
||||
.DEFAULT_GOAL := main
|
||||
|
||||
%: src/%.c
|
||||
$(CC) -o $@ $< $(CFLAGS) -I$(INCLUDES)
|
||||
|
||||
clean:
|
||||
rm main.exe
|
29
examples/many_register_mov.asm
Normal file
29
examples/many_register_mov.asm
Normal file
@ -0,0 +1,29 @@
|
||||
; ========================================================================
|
||||
;
|
||||
; (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 38
|
||||
; ========================================================================
|
||||
|
||||
bits 16
|
||||
|
||||
mov cx, bx
|
||||
mov ch, ah
|
||||
mov dx, bx
|
||||
mov si, bx
|
||||
mov bx, di
|
||||
mov al, cl
|
||||
mov ch, ch
|
||||
mov bx, ax
|
||||
mov bx, si
|
||||
mov sp, di
|
||||
mov bp, ax
|
19
examples/single_register_mov.asm
Normal file
19
examples/single_register_mov.asm
Normal file
@ -0,0 +1,19 @@
|
||||
; ========================================================================
|
||||
;
|
||||
; (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 37
|
||||
; ========================================================================
|
||||
|
||||
bits 16
|
||||
|
||||
mov cx, bx
|
15
include/os.h
Normal file
15
include/os.h
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
|
||||
#define IS_WINDOWS
|
||||
#elif defined(__linux__)
|
||||
#define IS_LINUX
|
||||
#else
|
||||
#error Unable to determine platform
|
||||
#endif
|
||||
|
||||
#if defined(IS_LINUX)
|
||||
#include <stdio.h>
|
||||
#define MAX_PATH_SIZE PATH_MAX
|
||||
#elif defined(IS_WINDOWS)
|
||||
#define MAX_PATH_SIZE 260
|
||||
#endif
|
83
src/cpu.c
Normal file
83
src/cpu.c
Normal file
@ -0,0 +1,83 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define u32 uint32_t
|
||||
#define u16 uint16_t
|
||||
#define u8 uint8_t
|
||||
|
||||
struct cpu_state {
|
||||
u16 ax, bx, cx, dx, sp, bp, si, di;
|
||||
};
|
||||
|
||||
const char *lookup_reg_name(u8 idx, bool wide) {
|
||||
if (wide) {
|
||||
if (idx == 0b000) {
|
||||
return "ax";
|
||||
} else if (idx == 0b001) {
|
||||
return "cx";
|
||||
} else if (idx == 0b010) {
|
||||
return "dx";
|
||||
} else if (idx == 0b011) {
|
||||
return "bx";
|
||||
} else if (idx == 0b100) {
|
||||
return "sp";
|
||||
} else if (idx == 0b101) {
|
||||
return "bp";
|
||||
} else if (idx == 0b110) {
|
||||
return "si";
|
||||
} else if (idx == 0b111) {
|
||||
return "di";
|
||||
}
|
||||
} else {
|
||||
if (idx == 0b000) {
|
||||
return "al";
|
||||
} else if (idx == 0b001) {
|
||||
return "cl";
|
||||
} else if (idx == 0b010) {
|
||||
return "dl";
|
||||
} else if (idx == 0b011) {
|
||||
return "bl";
|
||||
} else if (idx == 0b100) {
|
||||
return "ah";
|
||||
} else if (idx == 0b101) {
|
||||
return "ch";
|
||||
} else if (idx == 0b110) {
|
||||
return "dh";
|
||||
} else if (idx == 0b111) {
|
||||
return "bh";
|
||||
}
|
||||
}
|
||||
|
||||
printf("ERROR: Unknown register %d, wide %d", idx, wide);
|
||||
abort();
|
||||
}
|
||||
|
||||
void dissassemble(FILE *src, FILE *dst) {
|
||||
fprintf(dst, "bits 16\n\n");
|
||||
while (!feof(src)) {
|
||||
u8 byte1 = fgetc(src);
|
||||
u8 byte2 = fgetc(src);
|
||||
|
||||
if ((byte1 & 0b11111100) == 0b10001000) {
|
||||
bool wide = byte1 & 0b1;
|
||||
bool direction = (byte1 & 0b10) >> 1;
|
||||
|
||||
u8 mod = byte2 & 0b11000000;
|
||||
u8 reg = (byte2 & 0b00111000) >> 3;
|
||||
u8 rm = byte2 & 0b00000111;
|
||||
if (mod == 0b11000000) {
|
||||
const char *reg_name = lookup_reg_name(reg, wide);
|
||||
const char *rm_name = lookup_reg_name(rm, wide);
|
||||
if (direction) {
|
||||
fprintf(dst, "mov %s, %s\n", reg_name, rm_name);
|
||||
} else {
|
||||
fprintf(dst, "mov %s, %s\n", rm_name, reg_name);
|
||||
}
|
||||
} else {
|
||||
printf("ERROR: Unsupported mod '%d'", mod);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
51
src/main.c
Normal file
51
src/main.c
Normal file
@ -0,0 +1,51 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include "os.h"
|
||||
#include "cpu.c"
|
||||
#include <errno.h>
|
||||
|
||||
const char *get_tmp_dir() {
|
||||
#ifdef IS_WINDOWS
|
||||
char *dir;
|
||||
if ((dir = getenv("TMPDIR")) != NULL) return dir;
|
||||
if ((dir = getenv("TEMP")) != NULL) return dir;
|
||||
if ((dir = getenv("TMP")) != NULL) return dir;
|
||||
return NULL;
|
||||
#elif IS_LINUX
|
||||
return "/tmp";
|
||||
#endif
|
||||
}
|
||||
|
||||
void get_tmp_file(char *filename, const char *prefix) {
|
||||
const char *dir = get_tmp_dir();
|
||||
sprintf(filename, "%s\\%sXXXXXX", dir, prefix);
|
||||
int fd = mkstemp(filename);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int main() {
|
||||
char tmp_filename[MAX_PATH_SIZE];
|
||||
get_tmp_file(tmp_filename, "nasm_output");
|
||||
|
||||
char *example_filename = "examples/many_register_mov.asm";
|
||||
|
||||
char command[512] = { 0 };
|
||||
snprintf(command, sizeof(command), "nasm \"%s\" -o \"%s\"", example_filename, tmp_filename);
|
||||
if (system(command)) {
|
||||
printf("ERROR: Failed to compile '%s'", example_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *assembly = fopen(tmp_filename, "r");
|
||||
if (assembly == NULL) {
|
||||
printf("ERROR: Opening file '%s': %d\n", tmp_filename, errno);
|
||||
return -1;
|
||||
}
|
||||
dissassemble(assembly, stdout);
|
||||
fclose(assembly);
|
||||
|
||||
remove(tmp_filename);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user