2017-07-02 69 views
5

To jest mój kod CMontaż: Adres pamięci zmiennych w C Programowanie

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 

I to jest standardowe wyjście

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

To co widzę w 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) 

Adres dla zmiennych a & b ma być w 0x22ff4c & 0x22ff48 odpowiednio

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

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

Jednak jeśli spojrzeć na następujące GDB demontować wyjścia, adres nie był 0x22ff4c & 0x22ff48, ale 0x0040134e & 0x00401356

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

Ja również debugowania to na x32dbg, ale także ten sam adres. x32dbg

Jestem zdezorientowany. Co to jest, jeśli nie są one adresami pamięci dla zmiennych 0x0040134e ?

Odpowiedz

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

Nie, 0x0040134e i 0x00401356 nie są adresy zmiennych a i b. Zamiast tego są adresami instrukcji w kodzie, tj. instruction pointer IP. a i b inicjowane są w taki sposób:

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

tutaj adres a i besp+0x1c i esp+0x18 odpowiednio gdzie esp jest stack pointer. Jako adres otrzymujesz 0x22ff4c i 0x22ff48, z którego możesz łatwo odliczyć, że bieżący esp jest 0x22ff4c - 0x1c.

Należy pamiętać, że ta odpowiedź ignoruje podstawowe zarządzanie pamięcią wirtualną lub inne powiązane kwestie zarządzania pamięcią systemu operacyjnego, tj. W przypadku większości architektur 0x22ff4c i 0x22ff48 będzie adresem pamięci wirtualnej, a nie rzeczywistym adresem fizycznym pamięci RAM.