C语言读取内存中函数十六进制反汇编与预期不符,问题出在哪?
问题原因分析
- 你读取到的前9个字节是C编译器自动生成的函数栈帧初始化代码(函数序言),不属于你手写的内联汇编部分:
你输出的55 48 89 E5 89 7D FC 8B 55对应64位x86架构下的标准函数序言:
这部分是C函数默认会生成的前置逻辑,你直接从push rbp mov rbp, rsp mov DWORD PTR [rbp-0x4], edi ; 存储输入参数a到栈上 mov edx, DWORD PTR [rbp-0x4]Operation函数的起始地址拷贝机器码,自然会把这部分内容也包含进去。 - 内联汇编的约束使用导致生成指令不固定:你给输入输出参数用了
r约束,编译器会根据优化等级、寄存器占用情况自由选择绑定的寄存器,你手写的汇编指令实际生成的机器码会随编译参数变化,不一定和你预期的固定指令完全匹配。 - 反汇编时架构匹配问题:如果你是在64位环境下编译的程序,反汇编时误选32位x86架构解析,也会得到完全不符合预期的结果。
- 共享内存权限配置存在隐患:你代码中将
shm_perm.uid赋值为getpid()是错误的,uid是用户ID,getpid()返回的是进程ID,只是因为你当前进程的运行用户恰好是共享内存的所有者,才没有触发权限错误。
修复方案
- 如果要获取纯手写汇编的机器码,给
Operation函数添加__attribute__((naked))修饰符,编译器不会自动生成函数序言、栈帧处理、返回指令等额外代码,函数内的所有逻辑完全由你自己用汇编实现,示例:__attribute__((naked)) int Operation(int a) { __asm__( ".intel_syntax;" "mov eax, edi;" // 64位下第一个参数直接从rdi取,不需要用约束 "add eax, 1;" "add eax, 1;" "ret;" // 自己加返回指令 ".att_syntax;" ); } - 拷贝机器码前先通过objdump确认原函数的实际机器码:执行
objdump -M intel -d 你的可执行文件,找到Operation函数的实际汇编和对应机器码,确认符合预期后再进行拷贝操作。 - 反汇编共享内存的机器码时,选择和编译目标一致的架构,64位程序就用x86_64架构解析。
内容的提问来源于stack exchange,提问作者soon
相关产品推荐
相关产品推荐

