补完三个部分完成的Y86反汇编程序,使得程序能正确完整地完成反汇编功能,反汇编Y86架构中定义的所有指令。
分任务1:能正确反汇编机器操作码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int convertStrToByteCode(const char *str, unsigned char inst[], int size);
void disassembleInstruction(unsigned char instruction[], int size);
int main(int argc, char **argv)
{
FILE *pFile = NULL;
char buffer[15];
if (argc < 2)
{
pFile = fopen("./test1.txt", "r");
}
else
{
pFile = fopen(argv[1], "r");
}
if (pFile == NULL)
{
printf("Error open test file, please make sure they exist.");
return 0;
}
while (fgets(buffer, 15, pFile) && strlen(buffer) > 1)
{
unsigned char instruction[6] = {0, 0, 0, 0, 0, 0};
convertStrToByteCode(buffer, instruction, 6);
disassembleInstruction(instruction, 6);
}
fclose(pFile);
return 0;
}
int convertStrToByteCode(const char *str, unsigned char inst[], int size)
{
int numHexDigits = 0;
char *endstr;
numHexDigits = strlen(str) - 1;
long long value = strtol(str, &endstr, 16);
int numBytes = numHexDigits >> 1;
int byteCount = numHexDigits >> 1;
while (byteCount > 0)
{
unsigned long long mask = 0xFF;
unsigned long shift = (numBytes - byteCount) << 3;
inst[byteCount - 1] = (value & (mask << shift)) >> shift;
byteCount--;
}
return numHexDigits >> 1;
}
void disassembleInstruction(unsigned char instruction[], int size)
{
// TODO: Add your implementation here to disassemble the y86 opcodes and display the result.
// For example, you can use a switch statement or an array of function pointers to handle different opcodes.
// If an undisassembled opcode is found, display it as "TODO: undisassembled opcode".
}
分任务2:能正确反汇编寄存器操作数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//This is an array of register mnemonics in y86
const char *register_names[] =
{
"%eax",
"%ecx",
"%edx",
"%ebx",
"%esp",
"%ebp",
"%esi",
"%edi",
"UNKNOWN_REGSITER"};
int convertStrToByteCode(const char *str, unsigned char inst[], int size);
int main(int argc, char **argv)
{
FILE *pFile = NULL;
char buffer[15];
if (argc < 2)
{
pFile = fopen("./test1.txt", "r");
}
else
{
pFile = fopen(argv[1], "r");
}
if (pFile == NULL)
{
printf("Error open test file, please make sure they exist.\n");
return 0;
}
while (fgets(buffer, 15, pFile) && strlen(buffer) > 1)
{
//This unsigned char array stores an instruction read from the file
//As the largest y86 instruction is 6 bytes, there are 6 unsigned char in the array where
//each represents a byte.
unsigned char instruction[6] = {0, 0, 0, 0, 0, 0};
convertStrToByteCode(buffer, instruction, 6);
//TODO: From here, your task is to complete the implementation so that all y86 opcode and operands can be disassembled.
//Any undisassembled opcode should display as "TODO: undisassembled opcode and operands"
printf("TODO: undisassembled opcode and operands. The first byte of the instruction is 0x%X\n", instruction[0]);
}
fclose(pFile);
return 0;
}
/****************************************************************************
N.B. You do not need to modify or work in this function.
Description:
This function converts a line of machine code read from the text file
into machine byte code.
The machine code is stored in an unsigned char array.
******************************************************************************/
int convertStrToByteCode(const char *str, unsigned char inst[], int size)
{
int numHexDigits = 0;
char *endstr;
//Each instruction should consist of at most 12 hex digits
numHexDigits = strlen(str) - 1;
//Convert the string to integer, N.B. this integer is in decimal
long long value = strtol(str, &endstr, 16);
int numBytes = numHexDigits >> 1;
int byteCount = numHexDigits >> 1;
while (byteCount > 0)
{
unsigned long long mask = 0xFF;
unsigned long shift = (numBytes - byteCount) << 3;
inst[byteCount - 1] = (value & (mask << shift)) >> shift;
byteCount--;
}
//Return the size of the instruction in bytes
return numHexDigits >> 1;
}
分任务3:能正确反汇编立即数和存储器地址操作数。
#include <stdio.h>
#include <stdlib.h>
//This is the help function that reads y86 binary code from a file
unsigned int loadBinFromFile(const char *filename, unsigned char memory[], unsigned int memsize);
int main(int argc, char **argv)
{
unsigned int MAX_MEMSIZE = 4096;
unsigned char memory[MAX_MEMSIZE]; //This array represents the 4KB memory space
unsigned int PC = 0; //This is the initial program counter address
if (argc < 2)
{
printf("Usage: please specify a y86 binary program file in the argument.\n");
return -1;
}
unsigned int program_size = loadBinFromFile(argv[1], memory, MAX_MEMSIZE);
if (program_size == 0)
return 0;
//TODO: Implement your disassembler from here
//At the moment, it simply display each byte from the memory.
while (PC < program_size)
{
printf("%02X\n", memory[PC]);
PC++;
}
return 0;
}
/****************************************************************************
N.B. You do not need to modify or work in this function.
Description:
This function reads in a y86 machine bytecode from file and
store them in an unsigned char array.
******************************************************************************/
unsigned int loadBinFromFile(const char *filename, unsigned char memory[], unsigned int memsize)
{
unsigned int bytes_read = 0;
unsigned int file_size = 0;
FILE *pfile = fopen(filename, "rb");
if (!pfile)
{
printf("Unable to load file %s, please check if the path and name are correct.\n", filename);
return 0;
}
fseek(pfile, 0, SEEK_END);
file_size = ftell(pfile);
rewind(pfile);
if (file_size > memsize)
{
printf("Program size exceeds memory size of %d.\n", memsize);
return 0;
}
bytes_read = fread(memory, 1, file_size, pfile);
if (bytes_read != file_size)
{
printf("Bytes read does not match the file size.\n");
return 0;
}
fclose(pfile);
return bytes_read;
}