汇编:C编程中变量的内存地址

时间:2017-07-02 03:15:34

标签: c debugging assembly gdb ollydbg

这是我的C代码

C:\Codes>gdb test -q
Reading symbols from C:\Codes\test.exe...done.
(gdb) list 1,15
1       #include<stdio.h>
2
3       int main()
4       {
5               int a = 12345;
6               int b = 0x12345;
7               printf("+-----+-------+---------+----------+\n");
8               printf("| Var | Dec   | Hex     | Address  |\n");
9               printf("+-----+-------+---------+----------+\n");
10              printf("|  a  | %d | 0x%x  | %p |\n",a,a,&a);
11              printf("|  b  | %d | 0x%x | %p |\n",b,b,&b);
12              printf("+-----+-------+---------+----------+\n");
13
14              return 0;
15      }
(gdb) set disassembly-flavor intel

这是标准输出

C:\Codes>test
+-----+-------+---------+----------+
| Var | Dec   | Hex     | Address  |
+-----+-------+---------+----------+
|  a  | 12345 | 0x3039  | 0022FF4C |
|  b  | 74565 | 0x12345 | 0022FF48 |
+-----+-------+---------+----------+

这就是我在GDB中看到的

(gdb) break 7
Breakpoint 1 at 0x40135e: file test.c, line 7.
(gdb) run
Starting program: C:\Codes/test.exe
[New Thread 4044.0xab0]

Breakpoint 1, main () at test.c:7
7               printf("+-----+-------+---------+----------+\n");
(gdb) disassemble
Dump of assembler code for function main:
   0x00401340 <+0>:     push   ebp
   0x00401341 <+1>:     mov    ebp,esp
   0x00401343 <+3>:     and    esp,0xfffffff0
   0x00401346 <+6>:     sub    esp,0x20
   0x00401349 <+9>:     call   0x401990 <__main>
   0x0040134e <+14>:    mov    DWORD PTR [esp+0x1c],0x3039
   0x00401356 <+22>:    mov    DWORD PTR [esp+0x18],0x12345
=> 0x0040135e <+30>:    mov    DWORD PTR [esp],0x403024
   0x00401365 <+37>:    call   0x401c00 <puts>
   0x0040136a <+42>:    mov    DWORD PTR [esp],0x40304c
   0x00401371 <+49>:    call   0x401c00 <puts>
   0x00401376 <+54>:    mov    DWORD PTR [esp],0x403024
   0x0040137d <+61>:    call   0x401c00 <puts>
   0x00401382 <+66>:    mov    edx,DWORD PTR [esp+0x1c]
   0x00401386 <+70>:    mov    eax,DWORD PTR [esp+0x1c]
   0x0040138a <+74>:    lea    ecx,[esp+0x1c]
   0x0040138e <+78>:    mov    DWORD PTR [esp+0xc],ecx
   0x00401392 <+82>:    mov    DWORD PTR [esp+0x8],edx
   0x00401396 <+86>:    mov    DWORD PTR [esp+0x4],eax
   0x0040139a <+90>:    mov    DWORD PTR [esp],0x403071
   0x004013a1 <+97>:    call   0x401c08 <printf>
   0x004013a6 <+102>:   mov    edx,DWORD PTR [esp+0x18]
   0x004013aa <+106>:   mov    eax,DWORD PTR [esp+0x18]
   0x004013ae <+110>:   lea    ecx,[esp+0x18]
   0x004013b2 <+114>:   mov    DWORD PTR [esp+0xc],ecx
   0x004013b6 <+118>:   mov    DWORD PTR [esp+0x8],edx
   0x004013ba <+122>:   mov    DWORD PTR [esp+0x4],eax
   0x004013be <+126>:   mov    DWORD PTR [esp],0x40308c
   0x004013c5 <+133>:   call   0x401c08 <printf>
   0x004013ca <+138>:   mov    DWORD PTR [esp],0x403024
   0x004013d1 <+145>:   call   0x401c00 <puts>
   0x004013d6 <+150>:   mov    eax,0x0
   0x004013db <+155>:   leave
   0x004013dc <+156>:   ret
End of assembler dump.
(gdb)

变量地址a&amp; b应该在0x22ff4c&amp;分别为0x22ff48

(gdb) print &a
$1 = (int *) 0x22ff4c

(gdb) print &b
$2 = (int *) 0x22ff48

但是,如果您查看以下GDB反汇编输出,则地址不是0x22ff4c&amp; 0x22ff480x0040134e&amp; 0x00401356

   0x0040134e <+14>:    mov    DWORD PTR [esp+0x1c],0x3039
   0x00401356 <+22>:    mov    DWORD PTR [esp+0x18],0x12345

我也在x32dbg上调试了这个,但也得到了相同的地址。 x32dbg

我在这里感到很困惑。什么是0x0040134e&amp; 0x00401356如果它们不是变量a&amp;的内存地址b

1 个答案:

答案 0 :(得分:8)

0x0040134e <+14>:    mov    DWORD PTR [esp+0x1c],0x3039
0x00401356 <+22>:    mov    DWORD PTR [esp+0x18],0x12345

不,0x0040134e0x00401356不是变量ab的地址。相反,它们是代码中指令的地址,即instruction pointer IPab在以下行中初始化:

0x0040134e <+14>:    mov    DWORD PTR [esp+0x1c],0x3039
0x00401356 <+22>:    mov    DWORD PTR [esp+0x18],0x12345

此处ab的地址分别为esp+0x1cesp+0x18,其中espstack pointer。作为地址,您将获得0x22ff4c0x22ff48,您可以从中轻松扣除当前esp0x22ff4c - 0x1c

请注意,这个答案忽略了操作系统的底层虚拟内存管理或其他相关内存管理问题,即大多数架构0x22ff4c0x22ff48将是虚拟内存地址,而不是真实的物理地址你的RAM。