C 如何知道寄存器变量存储在哪里?

C 如何知道寄存器变量存储在哪里?,c,C,我知道寄存器变量存储在CPU寄存器中 如果CPU寄存器忙/满,则相同的变量存储在堆栈中 如何知道变量存储在堆栈或CPU寄存器中?不,不能 它是由编译器决定的,并且可能会在编译之间发生变化,例如,如果周围的代码更改或编译器标志更改。我同意Unwind先生的观点,但在某种程度上,这种方式可能会对您有所帮助: 文件名x.c: int main(){ register int i=0; i++; printf("%d",i); } 汇编代码: ~$ gcc x.c -S

我知道寄存器变量存储在CPU寄存器中

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

如何知道变量存储在堆栈或CPU寄存器中?

不,不能


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

我同意Unwind先生的观点,但在某种程度上,这种方式可能会对您有所帮助:

文件名
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    
您还可以使用
objdump
反汇编可执行文件:

$ 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
080483c4:
80483c4:55推力%ebp
80483c5:89 e5 mov%esp,%ebp
80483c7:83 e4 f0和$0xfffffff0,%esp
80483ca:53%推力ebx
80483cb:83 ec 1c低于$0x1c,%esp
80483ce:bb 00 mov$0x0,%ebx
80483d3:83 c3 01由于i添加$0x1,%ebx//++
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呼叫80482f4
80483e7:83 c4 1c添加$0x1c,%esp
80483ea:5b流行百分比ebx
80483eb:89 ec mov%ebp%esp
80483ed:5d pop%ebp
80483ee:c3 ret
80483ef:90 nop

%ebx
为寄存器变量保留的寄存器

我也同意解开的答案,另一方面,在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中。

根据Brian W.Kernighan和Dennis M.Ritchie(C语言的创始人)的《Ansi C编程语言-第二版》一书,你不能

第四章,第84页

“…并且不可能获取寄存器变量的地址, 无论变量是否实际放置在
寄存器中

希望有帮助! 祝你将来好运,
Ron

唯一确定的方法是检查编译器的汇编语言输出。你的假设是错误的,最后一个问题无法回答,因为你在这方面没有直接的控制权。@GregHewgill不是真的,此外,还有一些变量(如缓存量)依赖于硬件,您无法预测cpu将拥有多少缓存。即使你能读懂你的程序集:这有什么意义?@user1824407-不,缓存不会影响变量的寄存器和内存位置。只是有点迂腐,问题是他怎么知道它,而不是他怎么控制它。我同意Greg Hewgill的评论,您可以从汇编程序输出中确定。