mirror of
https://github.com/zoriya/dasm.git
synced 2025-12-06 06:36:31 +00:00
Rework 16bit read/write to handle endianess
This commit is contained in:
2
Makefile
2
Makefile
@@ -25,5 +25,5 @@ fclean: clean
|
||||
|
||||
re: fclean all
|
||||
|
||||
dbg: $(CFLAGS += -g)
|
||||
dbg: CFLAGS += -g -O0
|
||||
dbg: re
|
||||
|
||||
@@ -63,5 +63,8 @@ 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);
|
||||
|
||||
void *get_operand(const instruction_t *inst, unsigned i, state_t *state);
|
||||
operand_t get_operand(const instruction_t *inst, unsigned i, state_t *state);
|
||||
bool is_operand_wide(const instruction_t *inst, unsigned i);
|
||||
|
||||
void write_op(operand_t op, unsigned new_value);
|
||||
unsigned read_op(operand_t op);
|
||||
|
||||
@@ -4,18 +4,15 @@
|
||||
|
||||
void sub(const instruction_t *self, state_t *state)
|
||||
{
|
||||
void *from = get_operand(self, 0, state);
|
||||
void *to = get_operand(self, 1, state);
|
||||
unsigned old = is_operand_wide(self, 0) ? *(uint16_t *)from : *(uint8_t *)from;
|
||||
unsigned minus = is_operand_wide(self, 1) ? *(uint16_t *)to : *(uint8_t *)to;
|
||||
operand_t from = get_operand(self, 0, state);
|
||||
operand_t to = get_operand(self, 1, state);
|
||||
unsigned old = read_op(from);
|
||||
unsigned minus = read_op(to);
|
||||
unsigned value = old - minus;
|
||||
|
||||
if (is_operand_wide(self, 0))
|
||||
*(uint16_t *)from = value;
|
||||
else
|
||||
*(uint8_t *)from = value;
|
||||
write_op(from, value);
|
||||
|
||||
state->of = value != (is_operand_wide(self, 0) ? *(uint16_t *)from : *(uint8_t *)from);
|
||||
state->of = value != read_op(from);
|
||||
state->cf = old < minus;
|
||||
state->sf = value & (is_operand_wide(self, 0) ? 0x8000 : 0x80);
|
||||
state->zf = value == 0;
|
||||
|
||||
@@ -8,18 +8,16 @@
|
||||
|
||||
void mov(const instruction_t *self, state_t *state)
|
||||
{
|
||||
void *from = get_operand(self, 0, state);
|
||||
void *to = get_operand(self, 1, state);
|
||||
operand_t from = get_operand(self, 0, state);
|
||||
operand_t to = get_operand(self, 1, state);
|
||||
|
||||
if (is_operand_wide(self, 0))
|
||||
*(uint16_t *)from = *(uint16_t *)to;
|
||||
else
|
||||
*(uint8_t *)from = *(uint8_t *)to;
|
||||
// from = to;
|
||||
write_op(from, read_op(to));
|
||||
}
|
||||
|
||||
void push(const instruction_t *self, state_t *state)
|
||||
{
|
||||
uint16_t what = *(uint16_t *)get_operand(self, 0, state);
|
||||
unsigned what = read_op(get_operand(self, 0, state));
|
||||
|
||||
if (is_operand_wide(self, 0))
|
||||
state->memory[state->sp--] = what >> 8;
|
||||
@@ -28,7 +26,7 @@ void push(const instruction_t *self, state_t *state)
|
||||
|
||||
void call(const instruction_t *self, state_t *state)
|
||||
{
|
||||
uint16_t pc = *(uint16_t *)get_operand(self, 0, state);
|
||||
uint16_t pc = read_op(get_operand(self, 0, state));
|
||||
|
||||
state->memory[state->sp--] = state->pc >> 8;
|
||||
state->memory[state->sp--] = state->pc & 0xFF;
|
||||
@@ -37,7 +35,7 @@ void call(const instruction_t *self, state_t *state)
|
||||
|
||||
void jmp(const instruction_t *self, state_t *state)
|
||||
{
|
||||
uint16_t pc = *(uint16_t *)get_operand(self, 0, state);
|
||||
uint16_t pc = read_op(get_operand(self, 0, state));
|
||||
|
||||
state->pc = pc - get_inst_size(*self, state->binary + state->pc, state->binary_size - state->pc);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,36 @@
|
||||
#include "dasm.h"
|
||||
#include "interpretor.h"
|
||||
|
||||
void *get_reg_operand(state_t *state, bool is16bit, unsigned reg)
|
||||
void write_op(operand_t op, unsigned new_value)
|
||||
{
|
||||
switch (op.type) {
|
||||
case BIT8:
|
||||
*op.ptr = new_value;
|
||||
break;
|
||||
case BIT16_SMALL_ENDIAN:
|
||||
*(uint16_t *)op.ptr = new_value;
|
||||
break;
|
||||
case BIT16:
|
||||
op.ptr[0] = new_value & 0xFF;
|
||||
op.ptr[1] = new_value >> 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned read_op(operand_t op)
|
||||
{
|
||||
switch (op.type) {
|
||||
case BIT8:
|
||||
return *op.ptr;
|
||||
case BIT16_SMALL_ENDIAN:
|
||||
return *(uint16_t *)op.ptr;
|
||||
case BIT16:
|
||||
return op.ptr[0] | (op.ptr[1] << 8);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
operand_t get_reg_operand(state_t *state, bool is16bit, unsigned reg)
|
||||
{
|
||||
uint8_t *registers8[8] = {
|
||||
&state->al,
|
||||
@@ -29,12 +58,13 @@ void *get_reg_operand(state_t *state, bool is16bit, unsigned reg)
|
||||
&state->di,
|
||||
};
|
||||
|
||||
if (is16bit)
|
||||
return registers16[reg];
|
||||
return registers8[reg];
|
||||
return (operand_t){
|
||||
.ptr = is16bit ? (uint8_t *)registers16[reg]: registers8[reg],
|
||||
.type = is16bit ? BIT16_SMALL_ENDIAN : BIT8,
|
||||
};
|
||||
}
|
||||
|
||||
void *get_rm_operand(state_t *state, unsigned *imm_idx, bool is16bit)
|
||||
operand_t get_rm_operand(state_t *state, unsigned *imm_idx, bool is16bit)
|
||||
{
|
||||
unsigned mod = state->binary[state->pc + 1] >> 6;
|
||||
unsigned rm = state->binary[state->pc + 1] & 0b111;
|
||||
@@ -44,37 +74,50 @@ void *get_rm_operand(state_t *state, unsigned *imm_idx, bool is16bit)
|
||||
|
||||
if (mod == 0 && rm == 0b110) {
|
||||
*imm_idx += 2;
|
||||
return state->memory + state->binary[state->pc + state->parse_data.imm_idx];
|
||||
return (operand_t){
|
||||
.ptr = state->memory + state->binary[state->pc + state->parse_data.imm_idx],
|
||||
.type = is16bit ? BIT16 : BIT8
|
||||
};
|
||||
}
|
||||
int disp = mod == 0b10
|
||||
? *(uint16_t*)&state->binary[state->pc + state->parse_data.imm_idx]
|
||||
: (int8_t)state->binary[state->pc + state->parse_data.imm_idx];
|
||||
unsigned disp = read_op((operand_t){
|
||||
.ptr = &state->binary[state->pc + state->parse_data.imm_idx],
|
||||
.type = mod == 0b10 ? BIT16 : BIT8}
|
||||
);
|
||||
state->parse_data.imm_idx += mod == 0b10 ? 2 : 1;
|
||||
|
||||
operand_t ret = {.ptr = NULL, .type = is16bit ? BIT16 : BIT8};
|
||||
switch (rm) {
|
||||
case 0x00:
|
||||
return state->memory + state->bx + state->si + disp;
|
||||
ret.ptr = state->memory + state->bx + state->si + disp;
|
||||
break;
|
||||
case 0x01:
|
||||
return state->memory + state->bx + state->di + disp;
|
||||
ret.ptr = state->memory + state->bx + state->di + disp;
|
||||
break;
|
||||
case 0x02:
|
||||
return state->memory + state->bp + state->si + disp;
|
||||
ret.ptr = state->memory + state->bp + state->si + disp;
|
||||
break;
|
||||
case 0x03:
|
||||
return state->memory + state->bp + state->di + disp;
|
||||
ret.ptr = state->memory + state->bp + state->di + disp;
|
||||
break;
|
||||
case 0x04:
|
||||
return state->memory + state->si + disp;
|
||||
ret.ptr = state->memory + state->si + disp;
|
||||
break;
|
||||
case 0x05:
|
||||
return state->memory + state->di + disp;
|
||||
ret.ptr = state->memory + state->di + disp;
|
||||
break;
|
||||
case 0x06:
|
||||
return state->memory + state->bp + disp;
|
||||
ret.ptr = state->memory + state->bp + disp;
|
||||
break;
|
||||
case 0x07:
|
||||
return state->memory + state->bx + disp;
|
||||
ret.ptr = state->memory + state->bx + disp;
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *get_operand(const instruction_t *inst, unsigned i, state_t *state)
|
||||
operand_t get_operand(const instruction_t *inst, unsigned i, state_t *state)
|
||||
{
|
||||
void *ret = NULL;
|
||||
operand_t ret;
|
||||
unsigned imm_idx = 0;
|
||||
|
||||
switch (inst->mode[i]) {
|
||||
@@ -83,21 +126,24 @@ void *get_operand(const instruction_t *inst, unsigned i, state_t *state)
|
||||
FALLTHROUGHT;
|
||||
case IMM8:
|
||||
imm_idx++;
|
||||
ret = (void *)&state->binary[state->pc + state->parse_data.imm_idx];
|
||||
ret.ptr = &state->binary[state->pc + state->parse_data.imm_idx];
|
||||
ret.type = inst->mode[i] == IMM16 ? BIT16 : BIT8;
|
||||
break;
|
||||
case REL16:
|
||||
imm_idx += 2;
|
||||
state->parse_data.operand_holder[i] = state->pc
|
||||
+ get_inst_size(*inst, state->binary + state->pc, state->binary_size - state->pc)
|
||||
+ (int16_t)state->binary[state->pc + state->parse_data.imm_idx];
|
||||
ret = &state->parse_data.operand_holder[i];
|
||||
ret.ptr = &state->parse_data.operand_holder[i];
|
||||
ret.type = BIT16;
|
||||
break;
|
||||
case REL8:
|
||||
imm_idx++;
|
||||
state->parse_data.operand_holder[i] = state->pc
|
||||
+ get_inst_size(*inst, state->binary + state->pc, state->binary_size - state->pc)
|
||||
+ (int8_t)state->binary[state->pc + state->parse_data.imm_idx];
|
||||
ret = &state->parse_data.operand_holder[i];
|
||||
ret.ptr = &state->parse_data.operand_holder[i];
|
||||
ret.type = BIT8;
|
||||
break;
|
||||
case REG8:
|
||||
ret = get_reg_operand(state, false, (state->binary[state->pc + 1] & 0b111000) >> 3);
|
||||
@@ -176,9 +222,8 @@ void print_rm_value(state_t *state, instruction_t *inst)
|
||||
if (mod == 0b11)
|
||||
continue;
|
||||
|
||||
void *ptr = get_rm_operand(state, &imm, inst->mode[i] == R_M16);
|
||||
uint16_t val = inst->mode[i] == R_M16 ? *(uint16_t *)ptr : *(uint8_t *)ptr;
|
||||
printf(" ;[%04lx]%04x", (uint8_t *)ptr - state->memory, val);
|
||||
operand_t operand = get_rm_operand(state, &imm, inst->mode[i] == R_M16);
|
||||
printf(" ;[%04lx]%04x", operand.ptr - state->memory, read_op(operand));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ typedef struct state {
|
||||
unsigned imm_idx;
|
||||
// A bunch of unsigneds to store temporary operands and return them as pointers.
|
||||
// instructions can't write to it, they are effectivly read-only.
|
||||
unsigned operand_holder[5];
|
||||
uint8_t operand_holder[5];
|
||||
} parse_data;
|
||||
} state_t;
|
||||
|
||||
@@ -73,3 +73,15 @@ typedef struct {
|
||||
uint16_t source;
|
||||
uint16_t type;
|
||||
} syscall_t;
|
||||
|
||||
enum operand_type {
|
||||
BIT8,
|
||||
BIT16,
|
||||
BIT16_SMALL_ENDIAN,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t *ptr;
|
||||
enum operand_type type;
|
||||
} operand_t;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user