我知道寄存器变量存储在CPU寄存器中。
如果CPU寄存器忙/满,则相同的变量存储在堆栈中。
我怎么知道变量存储在堆栈或CPU寄存器中?
答案 0 :(得分:6)
不,你不能。
由编译器决定,如果周围的代码更改register pressure或者编译器标志发生更改,则可能会在编译之间进行更改。
答案 1 :(得分:6)
我同意Unwind先生的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 <printf@plt>
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
寄存器保留用于寄存器变量。
答案 2 :(得分: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)
此处对象i
和k
位于堆栈中,mont
位于寄存器$ s7中。
答案 3 :(得分:2)
根据Brian W. Kernighan所着的“The Ansi C Programming Language - Second Edition”一书。 Dennis M.Ritchie(C语言的创始人), 你不能 。
第4章,第84页,
“......并且不可能获取寄存器变量的地址, 无论变量是否实际放在
register
中。“
希望有所帮助! 祝你好运, 罗恩