当我在GDB中使用disas
命令与以下代码:
int main(){
char*a;
size_t r;
return 1;
}
我有这个结果:
0x080483db <+0>: push %ebp
0x080483dc <+1>: mov %esp,%ebp
0x080483de <+3>: mov $0x1,%eax
0x080483e3 <+8>: pop %ebp
0x080483e4 <+9>: ret
我不明白为什么没有char*a
和size*t
的说明。如何获得a
值和r
值的adress?它们甚至存在吗?
声明 char*a;
和 size_t r;
not 自己做任何事情 ;他们宁愿告诉编译器,您希望能够使用标识符a
和r
来存储值,而某些生命周期限于main
执行的持续时间。另一方面,大多数汇编说明(除了NOP等)做某事。
如果您在这些变量中存储并访问了值,或者采用它们的地址并使用了这些地址,以一种与与之相同的方式,而不是与之相同的方式,那么您会看到编译器发射代码可以腾出空间(通常是由调整堆栈指针,或将某些寄存器推入堆栈以保存其值,以使您的数据有额外的免费寄存器)并存储/加载值。
您需要进行实验,以使死代码没有优化。
unsigned int fun0 ( void )
{
return(0x12345678);
}
char * fun1 ( void )
{
char *x;
x = (char *)0x12345678;
return(x);
}
unsigned int fun2 ( unsigned int x )
{
return(x+12);
}
unsigned int * fun3 ( unsigned int *x )
{
return(x+3);
}
给出这样的东西
Disassembly of section .text:
00000000 <fun0>:
0: e59f0000 ldr r0, [pc] ; 8 <fun0+0x8>
4: e12fff1e bx lr
8: 12345678 eorsne r5, r4, #120, 12 ; 0x7800000
0000000c <fun1>:
c: e59f0000 ldr r0, [pc] ; 14 <fun1+0x8>
10: e12fff1e bx lr
14: 12345678 eorsne r5, r4, #120, 12 ; 0x7800000
00000018 <fun2>:
18: e280000c add r0, r0, #12
1c: e12fff1e bx lr
00000020 <fun3>:
20: e280000c add r0, r0, #12
24: e12fff1e bx lr
这里要注意的是,c语言具有 as-if 规则,该规则说该编译程序只需要产生相同的可观察行为。
由于您的程序的可观察行为等效于
的行为int main(){
return 1;
}
这就是编译的代码所做的。
这不适用于单独声明,并且可以任意复杂。例如,普通的Hello World程序:
#include <stdio.h>
int main(){
printf("Hello world!n");
}
具有可观察的行为等于
#include <stdio.h>
int main(){
puts("Hello world!");
}
后一个程序是如果您用-O3
编译前者,则获得的结果:
.LC0:
.string "Hello world!"
main:
leaq .LC0(%rip), %rdi
subq $8, %rsp
call puts@PLT
xorl %eax, %eax
addq $8, %rsp
ret