1-2 challenge: I_T_RM implemented

This commit is contained in:
Hane 2026-01-25 20:50:45 +01:00
commit f984261641
2 changed files with 185 additions and 8 deletions

Binary file not shown.

View file

@ -2,6 +2,9 @@
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
//TODO: Pass file struct and currently read bytes via param
enum DT_INSTRUCTIONS
{
@ -18,17 +21,20 @@ enum MOV_REGISTER_MODE
{
MEM_NO_DISP = 0b00,
MEM_8BIT_DISP = 0b01,
MEM_16BIT_DISP = 0b010,
MEM_16BIT_DISP = 0b10,
REG_NO_DISP = 0b11
};
#define REG_ENCODING_TXT_LEN 3
char REG_ENCODING_TXT[0b10000][REG_ENCODING_TXT_LEN] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"};
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
#define EA_ENCODING_TXT_LEN 8
char EA_ENCODING_TXT[0b1000][EA_ENCODING_TXT_LEN] = { "bx + si", "bx + di", "bp + si", "bp + di",
"si", "di", "bp", "bx"};
"si", "di", "bp", "bx" };
#define WORD_SIGNAL_LEN 6
char WORD_SIGNAL_TXT[0b10][WORD_SIGNAL_LEN] = { "byte ", "word " };
/* enum REG_ENCODING */
/* { */
@ -133,6 +139,167 @@ int MOV_I_T_R_parse(uint8_t byte1, uint8_t byte2, binary_data *binary, int bytes
return extra_bytes_read;
}
typedef struct {
char* string;
uint64_t len;
} output_string;
void fill_ea_string(output_string *str, char* content, int16_t displacement)
{
//EA STRING GENERATION
char* str_beg = str->string;
uint64_t disp_len = 0;
*(str->string) = '[';
str->string++;
str->len++;
memcpy(str->string, content, strlen(content));
str->string += strlen(content);
str->len += strlen(content);
if (displacement)
{
if (strlen(content) > 0)
{
memcpy(str->string, " + ", 3);
str->string += 3;
str->len += 3;
}
disp_len = sprintf(str->string, "%d", displacement);
str->string += disp_len;
str->len += disp_len;
}
*(str->string) = ']';
str->string = str_beg;
str->len += 2;
//END
return;
}
int MOV_I_T_RM_parse(uint8_t byte1, uint8_t byte2, binary_data *binary, int bytes_read)
{
const uint8_t wide_mask = 0b0000'0001;
const uint8_t mod_mask = 0b1100'0000;
const uint8_t regm_mask = 0b0000'0111;
unsigned char byte[1];
unsigned char payload[4];
uint8_t high_disp = 0;
uint16_t wide_disp = 0;
uint8_t high_data = 0;
uint16_t wide_data = 0;
bool is_wide = wide_mask & byte1;
uint8_t extra_bytes_read = 0;
//Effective Address string compose vars
char ea_string[18] = {'\0'};
char *ea_string_write_ptr = ea_string;
//Immediate value string compose vars
output_string mem_data;
mem_data.len = 0;
mem_data.string = calloc(18, sizeof(char)); //"[bp + di + 65535]\0"
//Number of chars disp value takes
int disp_len = 0;
enum MOV_REGISTER_MODE inst_mod = (byte2 & mod_mask) >> 6;
uint8_t extra_bytes = 1 + is_wide;
uint8_t reg_value = 0;
uint8_t ea_table_value = (byte2 & regm_mask);
switch (inst_mod)
{
case (REG_NO_DISP):
printf("Oh. This happened.\n");
//This shouldn't happen, right?
break;
case (MEM_NO_DISP):
//If R/M equals 110, there actually is displacement to worry about
bool is_direct_address = (ea_table_value == 0b110);
if (is_direct_address)
extra_bytes += 1 + is_wide;
for (int i = 0; i < extra_bytes; i++)
{
fread(&(payload[i]), sizeof(byte), 1, bin.binary);
extra_bytes_read++;
}
//Composing displacement and immediate values
if (is_direct_address)
{
wide_disp = payload[0];
if (is_wide)
{
wide_disp = (payload[1] << 8) + wide_disp;
wide_data = payload[2];
wide_data = (payload[3] << 8) + wide_data;
}
else
{
wide_data = payload[1];
}
}
else
{
wide_data = payload[0];
if (is_wide)
wide_data = (payload[1] << 8) + wide_data;
}
fill_ea_string(&mem_data, (is_direct_address ? "" : EA_ENCODING_TXT[ea_table_value]), wide_disp);
printf("%s %s, %s%d\n", "mov", mem_data.string, WORD_SIGNAL_TXT[is_wide], wide_data);
fprintf(output, "%s %s, %s%d\n", "mov", mem_data.string, WORD_SIGNAL_TXT[is_wide], wide_data);
break;
case (MEM_8BIT_DISP):
//If R/M equals 110, there actually is displacement to worry about
extra_bytes += 1;
for (int i = 0; i < extra_bytes; i++)
{
fread(&(payload[i]), sizeof(byte), 1, bin.binary);
extra_bytes_read++;
}
//Composing displacement and immediate values
wide_disp = payload[0];
wide_data = payload[1];
if (is_wide)
{
wide_data = (payload[2] << 8) + wide_data;
}
fill_ea_string(&mem_data, EA_ENCODING_TXT[ea_table_value], wide_disp);
printf("%s %s, %s%d\n", "mov", mem_data.string, WORD_SIGNAL_TXT[is_wide], wide_data);
fprintf(output, "%s %s, %s%d\n", "mov", mem_data.string, WORD_SIGNAL_TXT[is_wide], wide_data);
break;
case (MEM_16BIT_DISP):
//If R/M equals 110, there actually is displacement to worry about
extra_bytes += 2;
for (int i = 0; i < extra_bytes; i++)
{
fread(&(payload[i]), sizeof(byte), 1, bin.binary);
extra_bytes_read++;
}
//Composing displacement and immediate values
wide_disp = payload[0];
wide_disp = (payload[1] << 8) + wide_disp;
wide_data = payload[2];
if (is_wide)
{
wide_data = (payload[3] << 8) + wide_data;
}
fill_ea_string(&mem_data, EA_ENCODING_TXT[ea_table_value], wide_disp);
printf("%s %s, %s%d\n", "mov", mem_data.string, WORD_SIGNAL_TXT[is_wide], wide_data);
fprintf(output, "%s %s, %s%d\n", "mov", mem_data.string, WORD_SIGNAL_TXT[is_wide], wide_data);
break;
}
return extra_bytes_read;
}
int MOV_RM_TF_R_parse(uint8_t byte1, uint8_t byte2, binary_data *binary, int bytes_read)
{
@ -305,19 +472,29 @@ int main(int argc, char** argv)
for (int bytes_read = 0; bytes_read < bin.size; bytes_read++)
{
uint8_t inst_byte2 = 0;
fread(byte, sizeof(byte), 1, bin.binary);
uint8_t manip_inst = (uint8_t)byte[0];
uint8_t inst = (uint8_t)byte[0];
//We're checking for all MOV except segment registers
manip_inst = (manip_inst >> 1);
if (manip_inst == MOV_M_T_A || manip_inst == MOV_A_T_M)
{
switch (manip_inst)
{
case MOV_M_T_A:
case MOV_A_T_M:
if (bytes_read >= bin.size) break;
fread(byte, sizeof(byte), 1, bin.binary);
bytes_read++;
uint8_t inst_byte2 = (uint8_t)byte[0];
inst_byte2 = (uint8_t)byte[0];
bytes_read += MOV_MA_T_AM_parse(inst, inst_byte2, 0, 0, (manip_inst == MOV_M_T_A));
continue;
case MOV_I_T_RM:
if (bytes_read >= bin.size) break;
fread(byte, sizeof(byte), 1, bin.binary);
bytes_read++;
inst_byte2 = (uint8_t)byte[0];
bytes_read += MOV_I_T_RM_parse(inst, inst_byte2, 0, 0);
continue;
}
manip_inst = (manip_inst >> 1);
if (manip_inst == MOV_RM_TF_R)
@ -325,7 +502,7 @@ int main(int argc, char** argv)
if (bytes_read >= bin.size) break;
fread(byte, sizeof(byte), 1, bin.binary);
bytes_read++;
uint8_t inst_byte2 = (uint8_t)byte[0];
inst_byte2 = (uint8_t)byte[0];
bytes_read += MOV_RM_TF_R_parse(inst, inst_byte2, 0, 0);
continue;
}
@ -335,7 +512,7 @@ int main(int argc, char** argv)
if (bytes_read >= bin.size) break;
fread(byte, sizeof(byte), 1, bin.binary);
bytes_read++;
uint8_t inst_byte2 = (uint8_t)byte[0];
inst_byte2 = (uint8_t)byte[0];
bytes_read += MOV_I_T_R_parse(inst, inst_byte2, 0, 0);
continue;
}