gpt4 book ai didi

c - 解码C代码的等效汇编代码

转载 作者:行者123 更新时间:2023-12-02 05:35:20 25 4
gpt4 key购买 nike

为了查看一些 C 代码的编译器(汇编)输出,我用 C 编写了一个简单的程序并使用 gcc 生成了它的汇编文件。

代码是这样的:

#include <stdio.h>  

int main()
{
int i = 0;

if ( i == 0 )
{
printf("testing\n");
}

return 0;
}

为它生成的程序集在这里(只有main函数):

_main:  
pushl %ebpz
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
call __alloca
call ___main
movl $0, -4(%ebp)
cmpl $0, -4(%ebp)
jne L2
movl $LC0, (%esp)
call _printf
L2:
movl $0, %eax
leave
ret

我完全无法关联 C 代码和汇编代码。代码所要做的就是将 0 存储在寄存器中并将其与常量 0 进行比较并采取适当的措施。但是集会中发生了什么?

最佳答案

由于 main 是特殊的,您通常可以通过在另一个函数中执行此类操作来获得更好的结果(最好是在没有 main 的自己的文件中)。例如:

void foo(int x) {
if (x == 0) {
printf("testing\n");
}
}

作为汇编可能会更清楚。这样做还可以让您通过优化进行编译并仍然观察到条件行为。如果您要使用高于 0 的任何优化级别编译原始程序,它可能会取消比较,因为编译器可以继续计算结果。使用这段代码,比较的一部分对编译器是隐藏的(在参数 x 中),因此编译器无法进行此优化。

额外的东西实际上是什么

_main:  
pushl %ebpz
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp

这是为当前函数设置栈帧。在 x86 中,堆栈帧是堆栈指针的值(16、32 或 64 位的 SP、ESP 或 RSP)和基指针的值(BP、EBP 或 RBP)之间的区域。这应该是局部变量存在的地方,但实际上不是,在大多数情况下显式堆栈帧是可选的。不过,使用 alloca 和/或可变长度数组需要使用它们。

这种特殊的栈帧结构与非main 函数不同,因为它还确保栈是 16 字节对齐的。 ESP 的减法增加了堆栈大小,足以容纳局部变量,andl 有效地从 0 减到 15,使其 16 字节对齐。这种对齐方式似乎过分了,除了它会强制堆栈也开始缓存对齐和字对齐。

movl    $0, %eax  
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
call __alloca
call ___main

我不知道这一切是做什么的。 alloca 通过改变堆栈指针的值来增加堆栈帧的大小。

movl    $0, -4(%ebp)  
cmpl $0, -4(%ebp)
jne L2
movl $LC0, (%esp)
call _printf
L2:
movl $0, %eax

我想你知道这是做什么的。如果不是,则 call 之前的 movl 会将字符串的地址移动到堆栈的顶部位置,以便 printf 可以检索它。它必须在堆栈上传递,以便 printf 可以使用它的地址来推断 printf 的其他参数的地址(如果有的话,在这种情况下没有)。

leave  

这条指令删除了前面提到的栈帧。它本质上是 movl %ebp, %esp 后跟 popl %ebp。还有一个 enter 指令可以用来构造堆栈帧,但是 gcc 没有使用它。当未显式使用堆栈帧时,EBP 可用作通用寄存器,而不是 leave,编译器只会将堆栈帧大小添加到堆栈指针,这会将堆栈大小减少帧大小。

ret

这个不用多说了吧

当您使用优化进行编译时

我相信你会用不同的优化级别重新编译所有这些,所以我会指出一些你可能会觉得奇怪的可能发生的事情。我观察到 gcc 分别用 putsfputs 替换了 printffprintf,当格式字符串不包含任何 % 并且没有传递其他参数时。这是因为(出于多种原因)调用 putsfputs 的成本要低得多,而且最终您仍能得到想要打印的内容。

关于c - 解码C代码的等效汇编代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2988571/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com