Start to implement mov

This commit is contained in:
2023-07-05 11:10:43 +09:00
parent 1bba827d30
commit 6302e9b415
8 changed files with 158 additions and 39 deletions
+2 -1
View File
@@ -5,7 +5,8 @@ LDFLAGS =
SRC = src/main.c \
src/dasm.c \
src/instructions.c \
src/interpretor.c
src/interpretor.c \
src/instructions/memory.c
OBJ = $(SRC:%.c=%.o)
+5 -5
View File
@@ -34,7 +34,7 @@ int print_rm_operand(u_int8_t *binary, int imm_idx, bool is16bit)
if (mod == 0b01) {
int8_t disp_v = binary[imm_idx];
imm_offset++;
snprintf(disp, 20, "%c%x", disp_v < 0 ? '-' : '+', disp_v < 0 ? -disp_v : disp_v);
snprintf(disp, sizeof(disp), "%c%x", disp_v < 0 ? '-' : '+', disp_v < 0 ? -disp_v : disp_v);
}
switch (rm)
@@ -62,10 +62,10 @@ unsigned read_size(u_int8_t *binary, unsigned size)
return ret;
}
bool has_reg(instruction_t inst)
bool has_reg(const instruction_t *inst)
{
for (int i = 0; inst.mode[i] != END; i++) {
if (inst.mode[i] == REG8 || inst.mode[i] == REG16)
for (int i = 0; inst->mode[i] != END; i++) {
if (inst->mode[i] == REG8 || inst->mode[i] == REG16)
return true;
}
return false;
@@ -77,7 +77,7 @@ void print_instruction(unsigned addr, instruction_t inst, unsigned inst_size, u_
// if the instruction has already a param in it (ex `in al`), we need to directly add a comma.
// `jmp short` is an exception as it is the only instruction with a space in it that is not a parameter.
bool need_comma = !last_param && strchr(inst.name, ' ') && inst.opcode != 0xEB;
int imm_idx = 1 + (inst.extended != -1 || has_reg(inst));
int imm_idx = 1 + (inst.extended != -1 || has_reg(&inst));
printf("%04x:%s%0*x%-*s", addr, space ? " " : "", inst_size * 2, read_size(binary, inst_size), 14 - inst_size * 2, "");
if (last_param)
+8 -2
View File
@@ -4,6 +4,8 @@
#include <sys/types.h>
#include <stdbool.h>
#define FALLTHROUGHT __attribute__((fallthrough));
int dasm(u_int8_t *binary, unsigned long size);
int interpret(u_int8_t *binary, unsigned long size);
@@ -24,6 +26,10 @@ typedef enum addressing_mode {
REG8,
// 16bit register
REG16,
// 8bit register but stored inside the opcode
OPREG8,
// 16bit register but stored inside the opcode
OPREG16,
// Register or 8bit of memory
R_M8,
// Register or 16bit of memory
@@ -45,7 +51,7 @@ typedef struct instruction {
const char *name;
addressing_mode_t mode[5];
int extended;
void (*exec)(state_t *state);
void (*exec)(const struct instruction *self, state_t *state);
} instruction_t;
extern const instruction_t instructions[];
@@ -55,4 +61,4 @@ extern const instruction_t invalid_instruction;
instruction_t parse_inst(u_int8_t *binary, unsigned long size);
unsigned get_inst_size(instruction_t inst, u_int8_t *binary, unsigned bin_size);
void print_instruction(unsigned addr, instruction_t inst, unsigned inst_size, u_int8_t *binary, bool space);
bool has_reg(const instruction_t *inst);
+31 -30
View File
@@ -1,6 +1,7 @@
#include <stddef.h>
#include <stdio.h>
#include "dasm.h"
#include "instructions.h"
instruction_t parse_inst(u_int8_t *binary, unsigned long size)
{
@@ -27,8 +28,8 @@ const instruction_t instructions[] = {
{.opcode = 0x01, .extended = -1, .name = "add", .mode = {R_M16, REG16, END}, .exec = NULL},
{.opcode = 0x02, .extended = -1, .name = "add", .mode = {REG8, R_M8, END}, .exec = NULL},
{.opcode = 0x03, .extended = -1, .name = "add", .mode = {REG16, R_M16, END}, .exec = NULL},
{.opcode = 0x04, .extended = -1, .name = "add al", .mode = {IMM8, END}, .exec = NULL},
{.opcode = 0x05, .extended = -1, .name = "add ax", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0x04, .extended = -1, .name = "add al", .mode = {OPREG8, IMM8, END}, .exec = NULL},
{.opcode = 0x05, .extended = -1, .name = "add ax", .mode = {OPREG16, IMM16, END}, .exec = NULL},
{.opcode = 0x06, .extended = -1, .name = "push es", .mode = {END}, .exec = NULL},
{.opcode = 0x07, .extended = -1, .name = "pop es", .mode = {END}, .exec = NULL},
{.opcode = 0x08, .extended = -1, .name = "or", .mode = {R_M8, REG8, END}, .exec = NULL},
@@ -143,13 +144,13 @@ const instruction_t instructions[] = {
{.opcode = 0x85, .extended = -1, .name = "test", .mode = {R_M16, REG16, END}, .exec = NULL},
{.opcode = 0x86, .extended = -1, .name = "xchg", .mode = {R_M8, REG8, END}, .exec = NULL},
{.opcode = 0x87, .extended = -1, .name = "xchg", .mode = {R_M16, REG16, END}, .exec = NULL},
{.opcode = 0x88, .extended = -1, .name = "mov", .mode = {R_M8, REG8, END}, .exec = NULL},
{.opcode = 0x89, .extended = -1, .name = "mov", .mode = {R_M16, REG16, END}, .exec = NULL},
{.opcode = 0x8A, .extended = -1, .name = "mov", .mode = {REG8, R_M8, END}, .exec = NULL},
{.opcode = 0x8B, .extended = -1, .name = "mov", .mode = {REG16, R_M16, END}, .exec = NULL},
// {.opcode = 0x8C, .extended = -1, .name = "mov", .mode = {R_M16, sreg, END}, .exec = NULL},
{.opcode = 0x88, .extended = -1, .name = "mov", .mode = {R_M8, REG8, END}, .exec = &mov},
{.opcode = 0x89, .extended = -1, .name = "mov", .mode = {R_M16, REG16, END}, .exec = &mov},
{.opcode = 0x8A, .extended = -1, .name = "mov", .mode = {REG8, R_M8, END}, .exec = &mov},
{.opcode = 0x8B, .extended = -1, .name = "mov", .mode = {REG16, R_M16, END}, .exec = &mov},
// {.opcode = 0x8C, .extended = -1, .name = "mov", .mode = {R_M16, sreg, END}, .exec = &mov},
{.opcode = 0x8D, .extended = -1, .name = "lea", .mode = {REG16, R_M16, END}, .exec = NULL},
// {.opcode = 0x8E, .extended = -1, .name = "mov", .mode = {sreg, R_M16, END}, .exec = NULL},
// {.opcode = 0x8E, .extended = -1, .name = "mov", .mode = {sreg, R_M16, END}, .exec = &mov},
{.opcode = 0x8F, .extended = -1, .name = "pop", .mode = {R_M16, END}, .exec = NULL},
{.opcode = 0x90, .extended = -1, .name = "xchg ax, ax", .mode = {END}, .exec = NULL},
{.opcode = 0x91, .extended = -1, .name = "xchg cx, ax", .mode = {END}, .exec = NULL},
@@ -167,10 +168,10 @@ const instruction_t instructions[] = {
{.opcode = 0x9D, .extended = -1, .name = "popf", .mode = {END}, .exec = NULL},
{.opcode = 0x9E, .extended = -1, .name = "sahf", .mode = {END}, .exec = NULL},
{.opcode = 0x9F, .extended = -1, .name = "lahf", .mode = {END}, .exec = NULL},
// {.opcode = 0xA0, .extended = -1, .name = "mov al", .mode = {moffs16, END}, .exec = NULL},
// {.opcode = 0xA1, .extended = -1, .name = "mov ax", .mode = {moffs16, END}, .exec = NULL},
// {.opcode = 0xA2, .extended = -1, .name = "mov %s, al", .mode = {moffs16, END}, .exec = NULL},
// {.opcode = 0xA3, .extended = -1, .name = "mov %s, ax", .mode = {moffs16, END}, .exec = NULL},
// {.opcode = 0xA0, .extended = -1, .name = "mov al", .mode = {moffs16, END}, .exec = &mov},
// {.opcode = 0xA1, .extended = -1, .name = "mov ax", .mode = {moffs16, END}, .exec = &mov},
// {.opcode = 0xA2, .extended = -1, .name = "mov %s, al", .mode = {moffs16, END}, .exec = &mov},
// {.opcode = 0xA3, .extended = -1, .name = "mov %s, ax", .mode = {moffs16, END}, .exec = &mov},
{.opcode = 0xA4, .extended = -1, .name = "movsb", .mode = {END}, .exec = NULL},
{.opcode = 0xA5, .extended = -1, .name = "movsw", .mode = {END}, .exec = NULL},
{.opcode = 0xA6, .extended = -1, .name = "cmpsb", .mode = {END}, .exec = NULL},
@@ -183,29 +184,29 @@ const instruction_t instructions[] = {
{.opcode = 0xAD, .extended = -1, .name = "lodsw", .mode = {END}, .exec = NULL},
{.opcode = 0xAE, .extended = -1, .name = "scasb", .mode = {END}, .exec = NULL},
{.opcode = 0xAF, .extended = -1, .name = "scasw", .mode = {END}, .exec = NULL},
{.opcode = 0xB0, .extended = -1, .name = "mov al", .mode = {IMM8, END}, .exec = NULL},
{.opcode = 0xB1, .extended = -1, .name = "mov cl", .mode = {IMM8, END}, .exec = NULL},
{.opcode = 0xB2, .extended = -1, .name = "mov dl", .mode = {IMM8, END}, .exec = NULL},
{.opcode = 0xB3, .extended = -1, .name = "mov bl", .mode = {IMM8, END}, .exec = NULL},
{.opcode = 0xB4, .extended = -1, .name = "mov ah", .mode = {IMM8, END}, .exec = NULL},
{.opcode = 0xB5, .extended = -1, .name = "mov ch", .mode = {IMM8, END}, .exec = NULL},
{.opcode = 0xB6, .extended = -1, .name = "mov dh", .mode = {IMM8, END}, .exec = NULL},
{.opcode = 0xB7, .extended = -1, .name = "mov bh", .mode = {IMM8, END}, .exec = NULL},
{.opcode = 0xB8, .extended = -1, .name = "mov ax", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0xB9, .extended = -1, .name = "mov cx", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0xBA, .extended = -1, .name = "mov dx", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0xBB, .extended = -1, .name = "mov bx", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0xBC, .extended = -1, .name = "mov sp", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0xBD, .extended = -1, .name = "mov bp", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0xBE, .extended = -1, .name = "mov si", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0xBF, .extended = -1, .name = "mov di", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0xB0, .extended = -1, .name = "mov al", .mode = {IMM8, END}, .exec = &mov},
{.opcode = 0xB1, .extended = -1, .name = "mov cl", .mode = {IMM8, END}, .exec = &mov},
{.opcode = 0xB2, .extended = -1, .name = "mov dl", .mode = {IMM8, END}, .exec = &mov},
{.opcode = 0xB3, .extended = -1, .name = "mov bl", .mode = {IMM8, END}, .exec = &mov},
{.opcode = 0xB4, .extended = -1, .name = "mov ah", .mode = {IMM8, END}, .exec = &mov},
{.opcode = 0xB5, .extended = -1, .name = "mov ch", .mode = {IMM8, END}, .exec = &mov},
{.opcode = 0xB6, .extended = -1, .name = "mov dh", .mode = {IMM8, END}, .exec = &mov},
{.opcode = 0xB7, .extended = -1, .name = "mov bh", .mode = {IMM8, END}, .exec = &mov},
{.opcode = 0xB8, .extended = -1, .name = "mov ax", .mode = {IMM16, END}, .exec = &mov},
{.opcode = 0xB9, .extended = -1, .name = "mov cx", .mode = {IMM16, END}, .exec = &mov},
{.opcode = 0xBA, .extended = -1, .name = "mov dx", .mode = {IMM16, END}, .exec = &mov},
{.opcode = 0xBB, .extended = -1, .name = "mov bx", .mode = {IMM16, END}, .exec = &mov},
{.opcode = 0xBC, .extended = -1, .name = "mov sp", .mode = {IMM16, END}, .exec = &mov},
{.opcode = 0xBD, .extended = -1, .name = "mov bp", .mode = {IMM16, END}, .exec = &mov},
{.opcode = 0xBE, .extended = -1, .name = "mov si", .mode = {IMM16, END}, .exec = &mov},
{.opcode = 0xBF, .extended = -1, .name = "mov di", .mode = {IMM16, END}, .exec = &mov},
{.opcode = 0xC2, .extended = -1, .name = "ret", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0xC3, .extended = -1, .name = "ret", .mode = {END}, .exec = NULL},
{.opcode = 0xC4, .extended = -1, .name = "les", .mode = {REG16, R_M16, END}, .exec = NULL},
{.opcode = 0xC5, .extended = -1, .name = "lds", .mode = {R_M16, REG16, END}, .exec = NULL},
{.opcode = 0xC6, .extended = -1, .name = "mov", .mode = {R_M16, IMM8, END}, .exec = NULL},
{.opcode = 0xC7, .extended = -1, .name = "mov", .mode = {R_M16, IMM16, END}, .exec = NULL},
{.opcode = 0xC6, .extended = -1, .name = "mov", .mode = {R_M16, IMM8, END}, .exec = &mov},
{.opcode = 0xC7, .extended = -1, .name = "mov", .mode = {R_M16, IMM16, END}, .exec = &mov},
{.opcode = 0xCA, .extended = -1, .name = "retf", .mode = {IMM16, END}, .exec = NULL},
{.opcode = 0xCB, .extended = -1, .name = "retf", .mode = {END}, .exec = NULL},
{.opcode = 0xCC, .extended = -1, .name = "int3", .mode = {END}, .exec = NULL},
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include "dasm.h"
void mov(const instruction_t *self, state_t *state);
+98
View File
@@ -0,0 +1,98 @@
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include "../dasm.h"
unsigned *get_reg_operand(state_t *state, bool is16bit)
{
uint8_t *registers8[8] = {
&state->al,
&state->cl,
&state->dl,
&state->bl,
&state->ah,
&state->ch,
&state->dh,
&state->bh,
};
uint16_t *registers16[8] = {
&state->ax,
&state->cx,
&state->dx,
&state->bx,
&state->sp,
&state->bp,
&state->si,
&state->di,
};
if (is16bit)
return (void *)registers16[(state->binary[state->pc + 1] & 0b111000) >> 3];
return (void *)registers8[(state->binary[state->pc + 1] & 0b111000) >> 3];
}
unsigned *get_rm_operand(const instruction_t *inst, state_t *state, unsigned *imm_idx, bool is16bit)
{
unsigned mod = state->binary[1] >> 6;
unsigned rm = state->binary[1] & 0b111;
if (mod == 0b11)
return get_reg_operand(state, is16bit);
if (mod == 0 && rm == 0b110) {
*imm_idx += 2;
return (void *)&state->binary[state->pc + *imm_idx - 2];
}
// TODO:
return NULL;
}
unsigned *get_operand(const instruction_t *inst, unsigned i, state_t *state)
{
unsigned *ret = NULL;
unsigned imm_idx = 0;
switch (inst->mode[i]) {
case IMM16:
imm_idx++;
FALLTHROUGHT;
case IMM8:
imm_idx++;
ret = (void *)&state->binary[state->pc + state->parse_data.imm_idx];
break;
case REL16:
imm_idx++;
FALLTHROUGHT;
case REL8:
imm_idx++;
ret = NULL;
// TODO:
break;
case REG8:
ret = get_reg_operand(state, false);
break;
case REG16:
ret = get_reg_operand(state, true);
break;
case R_M8:
ret = get_rm_operand(inst, state, &imm_idx, false);
break;
case R_M16:
ret = get_rm_operand(inst, state, &imm_idx, true);
break;
case END:
printf("Invalid parameter read.");
break;
}
state->parse_data.imm_idx += imm_idx;
return ret;
}
void mov(const instruction_t *self, state_t *state)
{
unsigned *from = get_operand(self, 0, state);
unsigned *to = get_operand(self, 1, state);
printf("mov %p %p\n", from, to);
printf("mov %x %x\n", (uint16_t)*from, (uint16_t)*to);
}
+3 -1
View File
@@ -37,6 +37,7 @@ int interpret(u_int8_t *binary, unsigned long size)
}
binary += header_size;
state->binary = binary;
printf(" AX BX CX DX SP BP SI DI FLAGS IP\n");
while (state->pc < size) {
@@ -47,8 +48,9 @@ int interpret(u_int8_t *binary, unsigned long size)
}
print_state(state);
print_instruction(state->pc, inst, inst_size, binary, false);
state->parse_data.imm_idx = 1 + (inst.extended != -1 || has_reg(&inst));
if (inst.exec)
inst.exec(state);
inst.exec(&inst, state);
else
printf("Not implemented.\n");
state->pc += inst_size;
+6
View File
@@ -53,4 +53,10 @@ typedef struct state {
};
unsigned flags:10;
};
uint8_t *binary;
struct {
unsigned imm_idx;
} parse_data;
} state_t;