GCC编译的二进制文件中的冗余寄存器值? [复制]

Posted

技术标签:

【中文标题】GCC编译的二进制文件中的冗余寄存器值? [复制]【英文标题】:Redundant register values in GCC-compiled binary? [duplicate] 【发布时间】:2020-09-05 16:08:14 【问题描述】:

好的,所以我正在尝试学习逆向工程和 x64 汇编。作为一个例子,我用 C 编写了这个小测试程序:

#include <stdio.h>

int square(int num) 
        return num * num;


int main() 
        int ans = square(5);
        printf("%d", ans);

这导致square 函数的以下汇编代码:

push   rbp
mov    rbp,rsp
mov    DWORD PTR [rbp-0x4],edi
mov    eax,DWORD PTR [rbp-0x4]
imul   eax,eax
pop    rbp
ret

这对我来说似乎有点奇怪,因为edi 是函数参数,我相信它会存储在堆栈中并加载回eax,然后在其中相乘?为什么不跳过第 3 行和第 4 行而只跳过imul edi, edi? 所以我打开了radare2并这样做了,但现在程序返回看似随机的数字,我在猜测内存地址?

谁能向我解释为什么 GCC 使用这个看似多余的寄存器,以及我在尝试修补二进制文件时做错了什么?

【问题讨论】:

您使用了多少优化? (-O3?) 啊,我只是用默认设置编译它,O3优化的输出更有意义。谢谢! 【参考方案1】:

您没有启用优化,因此您正在查看调试代码。使用-O3,输出为:

关于您的问题的注释,您需要分配给eax,因为eax 将返回值存储在x86 应用程序中。

【讨论】:

对,这是有道理的。我发现我的补丁出了什么问题:edi 后来被 printf 的另一个参数覆盖:指向实际格式字符串的指针。 square的返回值应该在esi 这很好,因为edi是用来传递参数的。请记住,ediesi 是唯一可以运行 rep *sb 指令的寄存器,因此它们是很好的候选者。编译器(几乎)普遍使用一大堆约定,如果您真的想与编译器一起编写汇编代码,您需要了解它们,否则您将生成无效代码。 其实汇编编程现在可能有点野心勃勃,目前我主要只是想学习如何阅读编译器生成的汇编代码。但是感谢您的帮助,我真的很感激! 请不要张贴文字图片。您可以轻松地从 Godbolt 的 asm 输出窗格复制/粘贴文本。 但没有颜色格式。如果您不喜欢图片也没关系,如果它会改善其他人的生活,请随时添加您自己的无图片答案。

以上是关于GCC编译的二进制文件中的冗余寄存器值? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

GCC编译

程序的机器表示:

使用其他文件夹中的对象动态编译gcc

gcc 编译生成外部调试语法文件

当 gcc 中的应用程序在没有 gdb 的情况下崩溃时,如何生成堆栈转储和转储的寄存器值?

使用GCC的4位PowerPC CR0寄存器