C 带优化的反汇编代码局部变量保存在哪里
我是新来的装配工。我正在研究使用-g和-O3 fiag(优化)编译代码的差异 在优化代码的情况下,反汇编代码不会显示局部变量存储在堆栈上?我的理解是,无论何时调用任何函数,它都会跟踪堆栈上的局部变量,并在执行下一个函数时移动到下一个堆栈帧 下面是优化版本的反汇编代码C 带优化的反汇编代码局部变量保存在哪里,c,gdb,disassembly,C,Gdb,Disassembly,我是新来的装配工。我正在研究使用-g和-O3 fiag(优化)编译代码的差异 在优化代码的情况下,反汇编代码不会显示局部变量存储在堆栈上?我的理解是,无论何时调用任何函数,它都会跟踪堆栈上的局部变量,并在执行下一个函数时移动到下一个堆栈帧 下面是优化版本的反汇编代码 (gdb) disassemble main Dump of assembler code for function main: 0x00000000004004d0 <+0>: mov $0x1e,
(gdb) disassemble main
Dump of assembler code for function main:
0x00000000004004d0 <+0>: mov $0x1e,%eax
0x00000000004004d5 <+5>: retq
End of assembler dump.
(gdb) disassemble foo
Dump of assembler code for function foo:
0x00000000004004c0 <+0>: lea (%rsi,%rdi,1),%eax
0x00000000004004c3 <+3>: retq
End of assembler dump.
C没有关于局部变量必须存在于何处的规则——它们可以存在于堆栈、寄存器、内存中,也可以完全忽略 在您的示例中,您的大多数局部变量似乎已完全优化。在
-O3
gcc
中,如果局部变量只是偶然的临时变量,则会主动将变量移动到寄存器中,删除未使用的变量,并完全跳过它们。例如,在foo
中,gcc
将优化方法c
,并将加法结果直接存储在结果寄存器%eax
中。请注意,它根本不会将c=0;
编译到输出中,因为它知道c
会被下一条语句阻塞
在
main
中,z
和y
在输入foo
时具有已知的值,因此您的编译器只需内联foo
的定义。常量折叠和传播将main
简化为返回30;
,这根本不需要局部变量-这是您在t中看到的输出程序集(0x1e
=30)。C没有关于局部变量必须存在的位置的规则-它们可以存在于堆栈、寄存器、内存中,也可以完全省略
在您的示例中,您的大多数局部变量似乎已完全优化。在-O3
gcc
中,如果局部变量只是偶然的临时变量,则会主动将变量移动到寄存器中,删除未使用的变量,并完全跳过它们。例如,在foo
中,gcc
将优化方法c
,并将加法结果直接存储在结果寄存器%eax
中。请注意,它根本不会将c=0;
编译到输出中,因为它知道c
会被下一条语句阻塞
在
main
中,z
和y
在输入foo
时具有已知的值,因此您的编译器只需内联foo
的定义。常量折叠和传播将main
简化为返回30;
,这根本不需要局部变量-这是您在t中看到的输出汇编(0x1e
=30)。编译器注意到foo()
是一个可以内联编译的简单函数。然后它看到所有参数都是常量,因此它计算了结果。因此,您的main()
函数已优化为等效于:
int main() {
return 30;
}
$0x1e
是十六进制的数字30
编译foo()
时删除了变量c
,并将其编译为:
int foo(int a, int b) {
return a + b;
}
参数被传递到寄存器
RSI
和RDI
,它们被添加,总和被放入EAX
中以返回。编译器注意到foo()
是一个简单的函数,可以内联编译。然后它看到所有参数都是常数,因此计算结果。因此,您的main()
函数已优化为等效的:
int main() {
return 30;
}
$0x1e
是十六进制的数字30
编译foo()
时删除了变量c
,并将其编译为:
int foo(int a, int b) {
return a + b;
}
参数被传递到寄存器
RSI
和RDI
,并被添加,总和被放入EAX
中返回。局部变量可以保存在寄存器中。如果您想要一个有用的解释,您需要显示函数的源代码,然后有人可以解释如何存储局部变量ed.这是源代码。局部变量可以保存在寄存器中。如果你想要一个有用的解释,你需要显示函数的源代码,然后有人可以解释局部变量是如何存储的。这是源代码。