你怎么能告诉计算机它正在添加而没有 addl 在程序集中

How can you tell a computer it is adding without addl in Assembly

我对 Assembly 略知一二。那么我先介绍一下代码,再说说我的思路。

#This is the Assembly version.
pushq   %rbp
movq    %rsp, %rbp
movl    , -4(%rbp)
movl    , -8(%rbp)
movl    , %eax
popq    %rbp
ret


#This is the C version.
int twothree() {
    int a = 2;
    int b = 3;

    return 2 + 3;
}

好吧,首先让我吃惊的是,我们没有将变量a和b用作a + b。所以它们是不必要的,我们直接对整数求和。然而,如果计算机能够理解这一点,我想那将是非常可怕的。所以,我的问题是:这段汇编代码在没有任何 addl 或类似命令的情况下是如何工作的?我们直接将立即数(或常量)整数5移动到eax registrar.

另外,快速提问。那么最后两行之后的 a 和 b 变量会发生什么变化呢?他们在堆栈中的位置(或者我们可以称他们用作内存位置的 'registrars')现在是空闲的,因为我们使用 malloc + free。这是真的还是至少是合乎逻辑的? popq %rbp 我猜是关闭堆栈的命令。

正如我所说,我不是汇编方面的专家。所以这些想法大部分都只是在想。谢谢!

编译器发现您要将两个数字相加 2 + 3。编译器计算出 2+3=5 并将 5 放入汇编代码中。这叫做“不断折叠”。

我猜你在编译器中关闭了优化,因为它没有删除无用的变量 ab。但是常量折叠对编译器来说非常容易(不像其他类型的优化)并且很有用,所以即使你没有打开优化,编译器似乎也在做。

如您所见,汇编代码不会 添加 2 和 3,因为没有 addl 或类似的命令。它只是 return 5;

汇编编程中没有命令代码。相反,汇编代码(不可数)包含指令指令。

您在哪里看到 mallocfree 的用法?这些是用于管理 动态内存 的函数,这不是您的程序使用的东西。如果使用了这些函数中的任何一个,您将在某处的代码中有一个 call malloccall free 指令。变量ab都在自动存储,即栈上

现在您的代码中发生的情况是,编译器已执行 常量折叠 以发出代码,就像您编写的那样

#This is the C version.
int twothree() {
    int a = 2;
    int b = 3;

    return 5;
}

无论优化标志如何,编译器都会执行此操作。所以确实,在 运行 时间没有发生任何添加。它已经在编译时的常量折叠期间执行了。

Also, quick question. So what happens to the a and b variables after last two lines? Their position in stack (or maybe we can call the 'registrars' they used as a memory place) are free now as we use malloc + free. Is it true or at least logical? popq %rbp is the command for closing the stack I guess.

变量存储在红色区域, 堆栈指针下方的 128 字节内存区域,可免费用作暂存区,无需显式分配。因此,不需要代码为它们分配或释放存储空间。

现在,没有“关闭堆栈”这样的东西了。堆栈是内存中的一个区域。 栈指针rsp指向栈顶,而基指针rbp指向栈底当前堆栈帧。你会经常看到像

这样的代码
push %rbp
mov %rsp, %rbp
...
pop %rbp

在函数的开始和结束处建立和拆除堆栈帧。阅读组装教程了解更多详情。