Completed decoding the challenging mov instructions
This commit is contained in:
parent
e223314349
commit
620f9e0daa
2
8086_assembly_02/.gitignore
vendored
2
8086_assembly_02/.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
dasm
|
dasm
|
||||||
listing_0039_more_movs
|
listing_0039_more_movs
|
||||||
listing_0039_more_movs_out
|
listing_0039_more_movs_out
|
||||||
|
listing_0040_challenge_movs
|
||||||
|
listing_0040_challenge_movs_out
|
||||||
|
@ -1,11 +1,22 @@
|
|||||||
#include <bits/types/FILE.h>
|
#include <bits/types/FILE.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
enum class INST_MASKS {
|
enum class INST_BITS {
|
||||||
IMM_TO_REG = 0xb0,
|
|
||||||
REG_MEM_REG = 0x88,
|
REG_MEM_REG = 0x88,
|
||||||
|
MEM_TO_ACC = 0xa0,
|
||||||
|
ACC_TO_MEM = 0xa2,
|
||||||
|
IMM_TO_REG = 0xb0,
|
||||||
|
IMM_TO_REG_MEM = 0xc6,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class INST_MASKS {
|
||||||
|
REG_MEM_REG = 0xfc,
|
||||||
|
IMM_TO_REG = 0xf0,
|
||||||
|
IMM_TO_REG_MEM = 0xfe,
|
||||||
|
ACCUMULATOR = 0xfe,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class MODE {
|
enum class MODE {
|
||||||
@ -15,9 +26,13 @@ enum class MODE {
|
|||||||
REG = 0xc0,
|
REG = 0xc0,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool mask_instruction(uint8_t instruction, uint8_t mask);
|
bool mask_instruction(uint8_t instruction, uint8_t inst_bits, uint8_t mask);
|
||||||
void decode_register(uint8_t instruction, bool word, char *dest);
|
void decode_register(uint8_t instruction, bool word, char *dest);
|
||||||
void decode_rm(uint8_t instruction, char *dest);
|
void decode_rm(uint8_t instruction, char *dest);
|
||||||
|
void stringify_rm_and_disp(FILE *fp, uint8_t operands, char *rm,
|
||||||
|
uint32_t buff_size);
|
||||||
|
void handle_accumulator_mov_instructions(FILE *fp, uint8_t inst, bool reg_dest,
|
||||||
|
char *dest);
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
@ -42,30 +57,8 @@ int main(int argc, char *argv[]) {
|
|||||||
fprintf(out, "; Disassembled by DASM\n\nbits 16\n\n");
|
fprintf(out, "; Disassembled by DASM\n\nbits 16\n\n");
|
||||||
|
|
||||||
while (fread(&inst, sizeof(inst), 1, fp)) {
|
while (fread(&inst, sizeof(inst), 1, fp)) {
|
||||||
if (mask_instruction(inst, (uint8_t)INST_MASKS::IMM_TO_REG)) {
|
if (mask_instruction(inst, (uint8_t)INST_BITS::REG_MEM_REG,
|
||||||
op = "mov";
|
(uint8_t)INST_MASKS::REG_MEM_REG)) {
|
||||||
|
|
||||||
// Bit pattern is:
|
|
||||||
// 7 6 5 4 3 2 1 0
|
|
||||||
// -------------------------------
|
|
||||||
// | 1 | 0 | 1 | 1 | w | reg |
|
|
||||||
// -------------------------------
|
|
||||||
//
|
|
||||||
// So, we need to mask the fourth bit to check the w flag
|
|
||||||
bool word = mask_instruction(inst, 0x08);
|
|
||||||
|
|
||||||
uint8_t next_bytes = word ? 2 : 1;
|
|
||||||
|
|
||||||
char reg[3] = {0};
|
|
||||||
|
|
||||||
decode_register(inst, word, reg);
|
|
||||||
|
|
||||||
int16_t data = 0;
|
|
||||||
|
|
||||||
fread(&data, sizeof(next_bytes), next_bytes, fp);
|
|
||||||
|
|
||||||
fprintf(out, "%s %s, %d\n", op, reg, word ? data : (int8_t)data);
|
|
||||||
} else if (mask_instruction(inst, (uint8_t)INST_MASKS::REG_MEM_REG)) {
|
|
||||||
op = "mov";
|
op = "mov";
|
||||||
|
|
||||||
uint8_t operands = 0;
|
uint8_t operands = 0;
|
||||||
@ -83,14 +76,15 @@ int main(int argc, char *argv[]) {
|
|||||||
// | mod | reg | r/m |
|
// | mod | reg | r/m |
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
|
|
||||||
bool reg_dest = mask_instruction(inst, 0x02);
|
bool reg_dest = mask_instruction(inst, 0x02, 0x02);
|
||||||
|
|
||||||
bool word = mask_instruction(inst, 0x01);
|
bool word = mask_instruction(inst, 0x01, 0x01);
|
||||||
|
|
||||||
char reg[3] = {0};
|
char reg[3] = {0};
|
||||||
decode_register(operands >> 3, word, reg);
|
decode_register(operands >> 3, word, reg);
|
||||||
|
|
||||||
if (mask_instruction(operands, (uint8_t)MODE::REG)) {
|
if (mask_instruction(operands, (uint8_t)MODE::REG,
|
||||||
|
(uint8_t)MODE::REG)) {
|
||||||
char rm[3] = {0};
|
char rm[3] = {0};
|
||||||
decode_register(operands, word, rm);
|
decode_register(operands, word, rm);
|
||||||
|
|
||||||
@ -98,38 +92,78 @@ int main(int argc, char *argv[]) {
|
|||||||
reg_dest ? rm : reg);
|
reg_dest ? rm : reg);
|
||||||
} else {
|
} else {
|
||||||
char rm[20] = {0};
|
char rm[20] = {0};
|
||||||
decode_rm(operands, rm);
|
stringify_rm_and_disp(fp, operands, rm, 20);
|
||||||
|
|
||||||
bool direct_address = false;
|
|
||||||
|
|
||||||
uint8_t next_bytes = operands >> 6;
|
|
||||||
|
|
||||||
if (next_bytes == 0 && mask_instruction(operands, 0x06)) {
|
|
||||||
// Handle case when MOD == 00 and R/M == 110
|
|
||||||
next_bytes = 2;
|
|
||||||
|
|
||||||
direct_address = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t data = 0;
|
|
||||||
fread(&data, sizeof(next_bytes), next_bytes, fp);
|
|
||||||
|
|
||||||
if (data > 0) {
|
|
||||||
if (direct_address) {
|
|
||||||
memset(rm, 0, 20);
|
|
||||||
|
|
||||||
sprintf(rm, "%d", data);
|
|
||||||
} else {
|
|
||||||
char data_out[20] = {0};
|
|
||||||
sprintf(data_out, " + %d", data);
|
|
||||||
|
|
||||||
strcat(rm, data_out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(out, reg_dest ? "%s %s, [%s]\n" : "%s [%s], %s\n", op,
|
fprintf(out, reg_dest ? "%s %s, [%s]\n" : "%s [%s], %s\n", op,
|
||||||
reg_dest ? reg : rm, reg_dest ? rm : reg);
|
reg_dest ? reg : rm, reg_dest ? rm : reg);
|
||||||
}
|
}
|
||||||
|
} else if (mask_instruction(inst, (uint8_t)INST_BITS::IMM_TO_REG,
|
||||||
|
(uint8_t)INST_MASKS::IMM_TO_REG)) {
|
||||||
|
op = "mov";
|
||||||
|
|
||||||
|
// Bit pattern is:
|
||||||
|
// 7 6 5 4 3 2 1 0
|
||||||
|
// -------------------------------
|
||||||
|
// | 1 | 0 | 1 | 1 | w | reg |
|
||||||
|
// -------------------------------
|
||||||
|
//
|
||||||
|
// So, we need to mask the fourth bit to check the w flag
|
||||||
|
bool word = mask_instruction(inst, 0x08, 0x08);
|
||||||
|
|
||||||
|
uint8_t next_bytes = word ? 2 : 1;
|
||||||
|
|
||||||
|
char reg[3] = {0};
|
||||||
|
|
||||||
|
decode_register(inst, word, reg);
|
||||||
|
|
||||||
|
int16_t data = 0;
|
||||||
|
|
||||||
|
fread(&data, sizeof(next_bytes), next_bytes, fp);
|
||||||
|
|
||||||
|
fprintf(out, "%s %s, %d\n", op, reg, word ? data : (int8_t)data);
|
||||||
|
} else if (mask_instruction(inst, (uint8_t)INST_BITS::IMM_TO_REG_MEM,
|
||||||
|
(uint8_t)INST_MASKS::IMM_TO_REG_MEM)) {
|
||||||
|
op = "mov";
|
||||||
|
|
||||||
|
uint8_t operands = 0;
|
||||||
|
fread(&operands, sizeof(operands), 1, fp);
|
||||||
|
|
||||||
|
// Instruction bit pattern is:
|
||||||
|
// 7 6 5 4 3 2 1 0
|
||||||
|
// -------------------------------
|
||||||
|
// | 1 | 1 | 0 | 0 | 0 | 1 | 1 | w |
|
||||||
|
// -------------------------------
|
||||||
|
//
|
||||||
|
// Operands bit pattern is:
|
||||||
|
// 7 6 5 4 3 2 1 0
|
||||||
|
// -------------------------------
|
||||||
|
// | mod | 000 | r/m |
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
bool word = mask_instruction(inst, 0x01, 0x01);
|
||||||
|
|
||||||
|
char rm[20] = {0};
|
||||||
|
stringify_rm_and_disp(fp, operands, rm, 20);
|
||||||
|
|
||||||
|
uint8_t next_bytes = word ? 2 : 1;
|
||||||
|
|
||||||
|
int16_t data = 0;
|
||||||
|
fread(&data, sizeof(next_bytes), next_bytes, fp);
|
||||||
|
|
||||||
|
fprintf(out, "%s [%s], %s %d\n", op, rm, word ? "word" : "byte",
|
||||||
|
word ? data : (int8_t)data);
|
||||||
|
} else if (mask_instruction(inst, (uint8_t)INST_BITS::MEM_TO_ACC,
|
||||||
|
(uint8_t)INST_MASKS::ACCUMULATOR)) {
|
||||||
|
char inst_out[256] = {0};
|
||||||
|
handle_accumulator_mov_instructions(fp, inst, true, inst_out);
|
||||||
|
|
||||||
|
fprintf(out, "%s\n", inst_out);
|
||||||
|
} else if (mask_instruction(inst, (uint8_t)INST_BITS::ACC_TO_MEM,
|
||||||
|
(uint8_t)INST_MASKS::ACCUMULATOR)) {
|
||||||
|
char inst_out[256] = {0};
|
||||||
|
handle_accumulator_mov_instructions(fp, inst, false, inst_out);
|
||||||
|
|
||||||
|
fprintf(out, "%s\n", inst_out);
|
||||||
} else {
|
} else {
|
||||||
printf("It's not a mov operation\n");
|
printf("It's not a mov operation\n");
|
||||||
}
|
}
|
||||||
@ -148,8 +182,8 @@ int main(int argc, char *argv[]) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mask_instruction(uint8_t instruction, uint8_t mask) {
|
bool mask_instruction(uint8_t instruction, uint8_t inst_bits, uint8_t mask) {
|
||||||
return (instruction & mask) == mask;
|
return (instruction & mask) == inst_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_register(uint8_t instruction, bool word, char *dest) {
|
void decode_register(uint8_t instruction, bool word, char *dest) {
|
||||||
@ -196,3 +230,56 @@ void decode_rm(uint8_t instruction, char *dest) {
|
|||||||
|
|
||||||
strcpy(dest, table[index]);
|
strcpy(dest, table[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stringify_rm_and_disp(FILE *fp, uint8_t operands, char *rm,
|
||||||
|
uint32_t buff_size) {
|
||||||
|
decode_rm(operands, rm);
|
||||||
|
|
||||||
|
bool direct_address = false;
|
||||||
|
|
||||||
|
uint8_t next_bytes = operands >> 6;
|
||||||
|
|
||||||
|
if (next_bytes == 0 && mask_instruction(operands, 0x06, 0x06)) {
|
||||||
|
// Handle case when MOD == 00 and R/M == 110
|
||||||
|
next_bytes = 2;
|
||||||
|
|
||||||
|
direct_address = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t disp = 0;
|
||||||
|
fread(&disp, sizeof(next_bytes), next_bytes, fp);
|
||||||
|
|
||||||
|
if (disp != 0) {
|
||||||
|
if (direct_address) {
|
||||||
|
memset(rm, 0, buff_size);
|
||||||
|
|
||||||
|
sprintf(rm, "%d", disp);
|
||||||
|
} else {
|
||||||
|
bool positive = next_bytes > 1 ? disp > 0 : (int8_t)disp > 0;
|
||||||
|
|
||||||
|
char data_out[buff_size];
|
||||||
|
memset(data_out, 0, buff_size);
|
||||||
|
|
||||||
|
sprintf(data_out, " %c %d", positive ? '+' : '-',
|
||||||
|
next_bytes > 1 ? abs(disp) : abs((int8_t)disp));
|
||||||
|
|
||||||
|
strcat(rm, data_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_accumulator_mov_instructions(FILE *fp, uint8_t inst, bool reg_dest,
|
||||||
|
char *dest) {
|
||||||
|
bool word = mask_instruction(inst, 0x01, 0x01);
|
||||||
|
|
||||||
|
uint8_t next_bytes = word ? 2 : 1;
|
||||||
|
|
||||||
|
uint16_t addr = 0;
|
||||||
|
fread(&addr, sizeof(next_bytes), next_bytes, fp);
|
||||||
|
|
||||||
|
char addr_out[64] = {0};
|
||||||
|
sprintf(addr_out, "[%d]", word ? addr : (uint8_t)addr);
|
||||||
|
|
||||||
|
sprintf(dest, "mov %s, %s", reg_dest ? "ax" : addr_out,
|
||||||
|
reg_dest ? addr_out : "ax");
|
||||||
|
}
|
||||||
|
38
8086_assembly_02/listing_0040_challenge_movs.asm
Normal file
38
8086_assembly_02/listing_0040_challenge_movs.asm
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
; ========================================================================
|
||||||
|
;
|
||||||
|
; (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 40
|
||||||
|
; ========================================================================
|
||||||
|
|
||||||
|
bits 16
|
||||||
|
|
||||||
|
; Signed displacements
|
||||||
|
mov ax, [bx + di - 37]
|
||||||
|
mov [si - 300], cx
|
||||||
|
mov dx, [bx - 32]
|
||||||
|
|
||||||
|
; Explicit sizes
|
||||||
|
mov [bp + di], byte 7
|
||||||
|
mov [di + 901], word 347
|
||||||
|
|
||||||
|
; Direct address
|
||||||
|
mov bp, [5]
|
||||||
|
mov bx, [3458]
|
||||||
|
|
||||||
|
; Memory-to-accumulator test
|
||||||
|
mov ax, [2555]
|
||||||
|
mov ax, [16]
|
||||||
|
|
||||||
|
; Accumulator-to-memory test
|
||||||
|
mov [2554], ax
|
||||||
|
mov [15], ax
|
13
8086_assembly_02/listing_0040_challenge_movs_out.asm
Normal file
13
8086_assembly_02/listing_0040_challenge_movs_out.asm
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
bits 16
|
||||||
|
|
||||||
|
mov ax, [bx + di - 37]
|
||||||
|
mov [si - 300], cx
|
||||||
|
mov dx, [bx - 32]
|
||||||
|
mov [bp + di], byte 7
|
||||||
|
mov [di + 901], word 347
|
||||||
|
mov bp, [5]
|
||||||
|
mov bx, [3458]
|
||||||
|
mov ax, [2555]
|
||||||
|
mov ax, [16]
|
||||||
|
mov [2554], ax
|
||||||
|
mov [15], ax
|
Loading…
Reference in New Issue
Block a user