Implement the int instruction

This commit is contained in:
2023-07-06 14:30:40 +09:00
parent 012792f901
commit 8d2cd435d0
8 changed files with 70 additions and 9 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@ setuptools
._setuptools
*.o
dasm
.vgcore*

View File

@@ -23,3 +23,6 @@ fclean: clean
$(RM) $(NAME)
re: fclean all
dbg: $(CFLAGS += -g)
dbg: re

View File

@@ -3,5 +3,6 @@ pkgs.mkShell {
packages = with pkgs; [
gcc
gnumake
valgrind
];
}

View File

@@ -210,7 +210,7 @@ const instruction_t instructions[] = {
{.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},
{.opcode = 0xCD, .extended = -1, .name = "int", .mode = {IMM8, END}, .exec = NULL},
{.opcode = 0xCD, .extended = -1, .name = "int", .mode = {IMM8, END}, .exec = &int_inst},
{.opcode = 0xCE, .extended = -1, .name = "into", .mode = {END}, .exec = NULL},
{.opcode = 0xCF, .extended = -1, .name = "iret", .mode = {END}, .exec = NULL},
{.opcode = 0xD0, .extended = 7, .name = "EXTENDED", .mode = {END}, .exec = NULL},

View File

@@ -4,3 +4,4 @@
#include "interpretor.h"
void mov(const instruction_t *self, state_t *state);
void int_inst(const instruction_t *self, state_t *state);

View File

@@ -1,8 +1,11 @@
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "../dasm.h"
#include "../interpretor.h"
#include "sys/types.h"
void mov(const instruction_t *self, state_t *state)
{
@@ -14,3 +17,38 @@ void mov(const instruction_t *self, state_t *state)
else
*(uint8_t *)from = *(uint8_t *)to;
}
void int_inst(const instruction_t *self, state_t *state)
{
// I have no clue what the use of type is.
// uint8_t type = *(uint8_t *)get_operand(self, 0, state);
syscall_t *syscall = (syscall_t *)(state->memory + state->bx);
uint8_t *args = state->memory + state->bx + sizeof(*syscall);
(void)self;
switch (syscall->type) {
case 0x1:
printf("<exit(%d)>\n", *args);
exit(state->bx);
case 0x2:
printf("<fork() => %d>\n", 0);
printf("Not implemented\n");
break;
case 0x4: {
uint16_t fd = *(uint16_t *)args;
uint16_t len = *((uint16_t *)args + 1);
// the 2 args (a number is skiped.)
uint16_t addr = *((uint16_t *)args + 3);
printf("<write(%d, 0x%04x, %d)", fd, addr, len);
fflush(stdout);
int ret = write(fd, &state->memory[addr], len);
printf(" => %d>\n", ret);
state->ax = 0;
break;
}
default:
printf("Unimplemented syscall %02X\n", syscall->type);
break;
}
}

View File

@@ -1,4 +1,5 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include "dasm.h"
@@ -54,21 +55,21 @@ void *get_rm_operand(state_t *state, unsigned *imm_idx, bool is16bit)
switch (rm) {
case 0x00:
return state->binary + state->bx + state->si + disp;
return state->memory + state->bx + state->si + disp;
case 0x01:
return state->binary + state->bx + state->di + disp;
return state->memory + state->bx + state->di + disp;
case 0x02:
return state->binary + state->bp + state->si + disp;
return state->memory + state->bp + state->si + disp;
case 0x03:
return state->binary + state->bp + state->di + disp;
return state->memory + state->bp + state->di + disp;
case 0x04:
return state->binary + state->si + disp;
return state->memory + state->si + disp;
case 0x05:
return state->binary + state->di + disp;
return state->memory + state->di + disp;
case 0x06:
return state->binary + state->bp + disp;
return state->memory + state->bp + disp;
case 0x07:
return state->binary + state->bx + disp;
return state->memory + state->bx + disp;
}
return NULL;
}
@@ -169,19 +170,26 @@ int interpret(u_int8_t *binary, unsigned long size)
{
state_t *state = calloc(sizeof(*state), 1);
int header_size = 0;
int dsize= 0;
state->sp = 0xFFDC;
if (binary[0] == 0xEB && binary[1] == 0x0E) {
header_size = 16;
size = binary[2] | (binary[3] << 8);
dsize = binary[4] | (binary[5] << 8);
} else if (binary[0] == 0x01 && binary[1] == 0x03) {
header_size = binary[4];
size = binary[8] | (binary[9] << 8) | (binary[10] << 16) | (binary[11] << 24);
dsize = binary[12] | (binary[13] << 8) | (binary[14] << 16) | (binary[15] << 24);
}
binary += header_size;
state->binary = binary;
state->binary_size = size;
memcpy(state->memory, binary + size, dsize);
printf(" AX BX CX DX SP BP SI DI FLAGS IP\n");
while (state->pc < size) {
instruction_t inst = parse_inst(binary, size - state->pc);

View File

@@ -3,6 +3,8 @@
#include <stdint.h>
#include <stdbool.h>
#define MEMORY_SIZE 65536
typedef struct state {
union {
struct {
@@ -57,6 +59,8 @@ typedef struct state {
uint8_t *binary;
unsigned binary_size;
uint8_t memory[MEMORY_SIZE];
struct {
unsigned imm_idx;
// A bunch of unsigneds to store temporary operands and return them as pointers.
@@ -64,3 +68,8 @@ typedef struct state {
unsigned operand_holder[5];
} parse_data;
} state_t;
typedef struct {
uint16_t source;
uint16_t type;
} syscall_t;