C-当我们与GDB拆卸时,指针在哪里



当我在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*asize*t的说明。如何获得a值和r值的adress?它们甚至存在吗?

声明 char*a;size_t r; not 自己做任何事情 ;他们宁愿告诉编译器,您希望能够使用标识符ar来存储值,而某些生命周期限于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

最新更新