普通网友 2023-12-07 10:07 采纳率: 0%
浏览 31
已结题

用C语言反汇编y86指令

补完三个部分完成的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".
}

要求:输入10
90
6060
6237
6115
6332
2043
2143
2334
2241
2453
2642
2540
A028
A008
B058
00
输出
nop
ret
addl
andl
subl
xorl
rrmovl
cmovle
cmove
cmovl
cmovne
cmovg
cmovge
pushl
pushl
popl
halt
分任务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;
}

输入
10
90
6060
6237
6115
6332
2043
2143
2334
2241
2453
2642
2540
A028
A008
B058
00
输出

nop
ret
addl %esi, %eax
andl %ebx, %edi
subl %ecx, %ebp
xorl %ebx, %edx
rrmovl %esp, %ebx
cmovle %esp, %ebx
cmove %ebx, %esp
cmovl %esp, %ecx
cmovne %ebp, %ebx
cmovg %esp, %edx
cmovge %esp, %eax
pushl %edx
pushl %eax
popl %ebp
halt

分任务3:读取y86的二进制编码文件,正确反汇编立即数和存储器地址操作数。

#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;
}

  • 写回答

6条回答 默认 最新

  • 叫兽-郭老师 新星创作者: Java技术领域 2023-12-07 10:08
    关注

    由人工智能和答主提供,可以参考如下,如果回答的不正确,及时评论区回复,我追加回答,谢谢。
    分任务1:能正确反汇编机器操作码。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    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.\n");
            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;
    }
    
    void disassembleInstruction(unsigned char instruction[], int size)
    {
        switch (instruction[0])
        {
        case 0x00:
            printf("nop\n");
            break;
        case 0x10:
            printf("ret\n");
            break;
        case 0x20:
            printf("addl\n");
            break;
        case 0x30:
            printf("subl\n");
            break;
        case 0x40:
            printf("andl\n");
            break;
        case 0x50:
            printf("xorl\n");
            break;
        case 0x60:
            printf("rrmovl\n");
            break;
        case 0x70:
            printf("cmovle\n");
            break;
        case 0x80:
            printf("cmove\n");
            break;
        case 0x90:
            printf("cmovl\n");
            break;
        case 0xA0:
            printf("cmovne\n");
            break;
        case 0xB0:
            printf("cmovg\n");
            break;
        case 0xC0:
            printf("cmovge\n");
            break;
        case 0xD0:
            printf("pushl\n");
            break;
        case 0xE0:
            printf("popl\n");
            break;
        case 0xF0:
            printf("halt\n");
            break;
        default:
            printf("TODO: undisassembled opcode\n");
        }
    }
    

    分任务2:能正确反汇编寄存器操作数。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    const char *register_names[] =
        {
            "%eax",
            "%ecx",
            "%edx",
            "%ebx",
            "%esp",
            "%ebp",
            "%esi",
            "%edi",
            "UNKNOWN_REGISTER"};
    
    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.\n");
            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;
    }
    
    void disassembleInstruction(unsigned char instruction[], int size)
    {
        int opcode = instruction[0] & 0xF0;
    
        switch (opcode)
        {
        case 0x00:
            printf("nop\n");
            break;
        case 0x10:
            printf("ret\n");
            break;
        case 0x20:
        case 0x30:
        case 0x40:
        case 0x50:
        case 0x60:
        case 0x70:
        case 0x80:
        case 0x90:
        case 0xA0:
        case 0xB0:
        case 0xC0:
        case 0xD0:
        case 0xE0:
        case 0xF0:
            printf("%s %s, %s\n", register_names[instruction[1] & 0xF], register_names[(instruction[1] >> 4) & 0xF], register_names[(instruction[1] >> 4) & 0xF]);
            break;
        default:
            printf("TODO: undisassembled opcode\n");
        }
    }
    

    分任务3:读取y86的二进制编码文件,正确反汇编立即数和存储器地址操作数。

    #include <stdio.h>
    #include <stdlib.h>
    
    void disassembleInstruction(unsigned char instruction[], int size);
    
    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];
        unsigned int PC = 0;
    
        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;
    
        while (PC < program_size)
        {
            disassembleInstruction(memory + PC, 1);
            PC++;
        }
    
        return 0;
    }
    
    void disassembleInstruction(unsigned char instruction[], int size)
    {
        int opcode = instruction[0] & 0xF0;
    
        switch (opcode)
        {
        case 0x00:
            printf("nop\n");
            break;
        case 0x10:
            printf("ret\n");
            break;
        case 0x20:
        case 0x30:
        case 0x40:
        case 0x50:
        case 0x
    
    60:
        case 0x70:
        case 0x80:
        case 0x90:
        case 0xA0:
        case 0xB0:
        case 0xC0:
        case 0xD0:
        case 0xE0:
        case 0xF0:
            printf("TODO: Handle immediate values and memory addresses\n");
            break;
        default:
            printf("TODO: undisassembled opcode\n");
        }
    }
    
    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;
    }
    
    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 12月7日
  • 创建了问题 12月7日