C 中自定义操作码的反汇编逻辑

如何解决C 中自定义操作码的反汇编逻辑

所以我正在构建一个反汇编程序,它将包含十六进制数据的文件转换为汇编语言。

因此,从这种格式中,我可以使用 uint8_t 将文件中的十六进制数据转换为十进制并将它们存储在数组中。然后我决定对数组中的最后一个数字进行位移以获得最后一个函数的指令数;基本上我是在向后解析,因为我不知道开头有多少填充,并且函数中的操作数在函数末尾给出。但后来我意识到这些操作的位大小不同,并且不在完美的 8 位或 16 位范围内。然后我被卡住了,因为我的数组,使用顶部的例子,本质上是这样的:

uint8_t hex[] = {0x00,0x03,0x02,0x01,0x42,0x82,0x86,0x04,0x10,0x45};

那么谁能帮我解析逻辑?这是我第一次发帖,所以如果我遗漏了什么,我很抱歉,如果需要,我会提供更多信息或删除

解决方法

如果将 uint8_t 数组转换为位数组,而不是移位和屏蔽(我认为这会非常复杂)会怎样 - 它使用更多内存,但您可以更轻松地访问单个位。

这是一个执行此操作的示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

uint8_t getBits(uint8_t *bits,uint8_t size,uint32_t *index)
{
    uint8_t value = 0;
    *index -= size; // decrement index to the starting point
    for(uint32_t i=0; i<size; i++)
        value = (value<<1) | bits[*index+i];
    return value;
}

int main()
{
    // sample program
    uint8_t array[] = {0x00,0x03,0x02,0x01,0x42,0x82,0x86,0x04,0x10,0x45};
    
    // program with zero padding
    // uint8_t array[] = {0xE8,0x39,0x06,0xA0,0xC4,0x16,0x90,0x4A,0x08,0x41};
    
    uint32_t array_size = sizeof(array)/sizeof(*array); // 10 bytes
    uint32_t bits_size = 8*array_size; // 80 bytes
    uint8_t* bits = malloc(bits_size);
    
    for(uint32_t a=0;a<array_size;a++)
        for(uint32_t b=0;b<8;b++)
            bits[a*8+b] = (array[a] >> (7-b)) & 1;
    
    puts("Binary program file:");
    for(uint32_t i=0;i<bits_size;i++)
        printf("%s%d",(i%8?"":" "),bits[i]);
    puts("");
    
    enum                    {  MOV,CAL,RET,REF,ADD,PRINT,NOT,EQU};
    uint8_t params[]      = {    2,1,2,1};
    const char *opcodes[] = {"MOV","CAL","RET","REF","ADD","PRINT","NOT","EQU"};

    enum                    {  VAL,REG,STK,PTR};
    uint8_t value_size[]  = {    8,3,5,5};
    const char *types[]   = {"VAL","REG","STK","PTR"};

    uint32_t index = bits_size; // start at end
    
    // minimum program size is function(3) + opcode(3) + size(5)
    // if there are less than that number of bits then it must be padding
    while(index>10)
    {
        uint8_t size = getBits(bits,&index);
        printf("\nsize=%d\n",size);
        if (size > 0)
        {
            for(int o=0; o<size; o++)
            {
                uint8_t opcode = getBits(bits,&index);
                printf("opcode=%s",opcodes[opcode]);
                
                for(int p=0; p<params[opcode]; p++)
                {
                    printf("%c ",p?',':':');
                    
                    uint8_t type = getBits(bits,&index);
                    printf("type=%s ",types[type]);
                    
                    uint8_t value = getBits(bits,value_size[type],&index);
                    printf("value=%d",value);
                }
                
                puts("");
            }
        
            uint8_t function = getBits(bits,&index);
            printf("function=%d\n",function);
        }
    }
    return 0;
}

https://onlinegdb.com/S1qVStz8d 尝试

它是如何getBits()工作的:

您从原始值中创建一个由单个数字组成的数组,然后一次从它中取出一个位来创建一个新值 - getBits() 是我为此编写的函数。

要了解它是如何工作的,请想象一下它在基数 10 中是如何工作的:321 被放入数组 {3,1} 中,您可以使用以下命令将其转回一个值:

value = 0;
value = value*10 + digits[0];
value = value*10 + digits[1];
value = value*10 + digits[2];

哪个给出 (((0)*10+3)*10+2)*10+1321

如果将 5(二进制 101)放入数组 {1,1} 中,您可以使用以下命令将其重新转换为值:

value = 0;
value = value*2 + bits[0];
value = value*2 + bits[1];
value = value*2 + bits[2];

给出 (((0)*2+1)*2+0)*2+15(二进制 101

确实有效。一个体面的编译器会将 *2 优化为 <<1,将 + 优化为 |,但您可以自己完成(我就是这样做的):

value = 0;
value = (value<<1) | bits[0];
value = (value<<1) | bits[1];
value = (value<<1) | bits[2];

产生相同的二进制 00000101

这只是一个可读性问题 - 对于十进制,您希望看到 value*10+x,但对于二进制,您希望看到诸如移位/或数学运算之类的位运算,例如乘法/加法。

然后,如果你使用一个循环的大小和一个指向数组末尾的索引,你会得到:

uint8_t value = 0;
index -= size; // decrement index to the starting point
for(uint32_t i=0; i<size; i++)
    value = (value<<1) | bits[index+i];

但是,当然,如果它是一个函数,那么 index 需要是一个指针,你需要在任何地方取消引用它:

uint8_t getBits(uint8_t *bits,uint32_t *index)
{
    uint8_t value = 0;
    *index -= size; // decrement index to the starting point
    for(uint32_t i=0; i<size; i++)
        value = (value<<1) | bits[*index+i];
    return value;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res