2012-12-27 129 views
5

我知道寄存器变量存储在CPU寄存器中。如何知道寄存器变量存储在哪里?

如果CPU寄存器忙/满,则相同的变量将存储在堆栈中。

我怎么知道变量存储在堆栈或CPU寄存器中?

+1

的只有这样才能知道是从你的编译器检查汇编语言输出 –

+0

你的假设是错误的,最后一个问题不能回答,因为你没有直接控制在这 – user1824407

+0

@GregHewgill不是真的,也有变量如硬件依赖的缓存数量,并且无法预测CPU的缓存数量,即使哟你可以阅读你的程序集:有什么意义? – user1824407

回答

6

我同意放松身心的先生answer,但高达一定程度上这种方式可能对你有帮助:

文件名x.c

int main(){ 
    register int i=0; 
    i++; 
    printf("%d",i); 
} 

汇编代码:

~$ gcc x.c -S 

输出文件名是x.s

在我的情况下,使用ebx寄存器,这可能在不同的编译时间有所不同。

~$ cat x.s 
    .file "x.c" 
    .section .rodata 
.LC0: 
    .string "%d" 
    .text 
.globl main 
    .type main, @function 
main: 
    pushl %ebp 
    movl %esp, %ebp 
    andl $-16, %esp 
    pushl %ebx 
    subl $28, %esp 
    movl $0, %ebx 
    addl $1, %ebx    // because i++ 
    movl $.LC0, %eax 
    movl %ebx, 4(%esp) 
    movl %eax, (%esp) 
    call printf 
    addl $28, %esp 
    popl %ebx 
    movl %ebp, %esp 
    popl %ebp 
    ret  

您也可以使用objdunp拆卸可执行

$ gcc x.c -o x 
$ objdump x -d 

部分组件输出使用objdump命令:用于寄存器变量保留

080483c4 <main>: 
80483c4: 55      push %ebp 
80483c5: 89 e5     mov %esp,%ebp 
80483c7: 83 e4 f0    and $0xfffffff0,%esp 
80483ca: 53      push %ebx 
80483cb: 83 ec 1c    sub $0x1c,%esp 
80483ce: bb 00 00 00 00   mov $0x0,%ebx 
80483d3: 83 c3 01    add $0x1,%ebx   //due to i++ 
80483d6: b8 b0 84 04 08   mov $0x80484b0,%eax 
80483db: 89 5c 24 04    mov %ebx,0x4(%esp) 
80483df: 89 04 24    mov %eax,(%esp) 
80483e2: e8 0d ff ff ff   call 80482f4 <[email protected]> 
80483e7: 83 c4 1c    add $0x1c,%esp 
80483ea: 5b      pop %ebx 
80483eb: 89 ec     mov %ebp,%esp 
80483ed: 5d      pop %ebp 
80483ee: c3      ret  
80483ef: 90      nop 

%ebx寄存器。

6

不,你不能。

它是由编译器决定,如果,例如,周围的代码更改register pressure或者如果编译器标志改变汇编之间可能会发生变化。

+3

只是有些迂腐的问题确实说他怎么能知道它,而不是如何控制它。我同意Greg Hewgill的评论,你可以从汇编输出中确定。 – PeterJ

3

我同意UnWind的答案,另一方面,反汇编GDB中的代码可能会给变量的存储空间。拆卸一个模糊的代码,我给下面的该帧的当地人,

(gdb) info locals 
i = 0 
ret = <value optimized out> 
k = 0 
ctx = (BN_CTX *) 0x632e1cc8 
A1 = (BIGNUM *) 0x632e1cd0 
A1_odd = (BIGNUM *) 0x632e1ce8 
check = <value optimized out> 
mont = (BN_MONT_CTX *) 0x632e2108 
A = (const BIGNUM *) 0x632e2028 

现在,如果尝试打印当地人它不告诉我下面的存储位置的地址,

(gdb) p &i 
$16 = (int *) 0x143fba40 
(gdb) p &k 
$17 = (int *) 0x143fba38 
(gdb) p &mont 
Address requested for identifier "mont" which is in register $s7 
(gdb) 

这里对象ik处于堆栈并且mont处于注册$ s7中。

1

据书“的ANSI C编程语言 - 第二版”布赖恩W. Kernighan的&丹尼斯M.Ritchie的(该C语言的创始人),你不能

第4章,第84页,

” ...它是不可能拿寄存器变量, 地址不管变量是否真正放在register。”

希望帮助! 祝您好运在未来, 罗恩