GCC编译C生成x86_64汇编混有32/64位指令的问题咨询
x86_64汇编混合指令与修改段错误问题解析
为什么汇编会混合32位和64位指令?
这是GCC的正常编译行为:
- C语言中
int类型默认是32位,x86_64架构下用32位寄存器(%edi、%esi)和32位指令(movl)就能完整存储数据,还能缩短指令长度。 - 指针是64位,必须用64位寄存器(
%rdx)和64位指令(movq)处理,因此会出现两种指令混合的情况。
修改%edi正常、%esi出错的原因
和16字节栈对齐无关,核心问题是栈布局被破坏导致数据覆盖:
- 原代码中
movl %esi, -24(%rbp)是把32位的%esi存入栈上4字节的区间(-24(%rbp)到-20(%rbp))。 - 若改成
movq %rsi, -24(%rbp),64位的%rsi会占用8字节(-24(%rbp)到-16(%rbp)),直接覆盖了原本存储第一个整数参数的-20(%rbp)位置。后续代码访问该位置时会读取到错误数据,最终触发段错误。 - 修改
%edi时未触发问题,只是因为该位置后续没有被依赖的代码访问,属于侥幸正常运行,本质上同样破坏了栈布局。
正确的处理方式
如果想让GCC生成全64位指令处理整数,直接把C代码里的int类型改成long(x86_64下long为64位),再执行gcc -O0 -S my_C_code.c重新编译即可。此时GCC会自动使用%rdi、%rsi这类64位寄存器及对应指令,无需手动修改汇编代码。
内容的提问来源于stack exchange,提问作者Dremond Williams
相关产品推荐
相关产品推荐

