2013-07-09 4 views
5

Fonte:Come l'offset arriva nello stack? Codice

1  int func() 
2  { 
3   int a = 0x12345678; 
4   int *p = &a; 
5   return *p; 
6  } 

8  int main() 
9  { 
10   int b = 0x87654321; 
11   return b + func(); 
12  } 

Smontare:

(gdb) disass main 
Dump of assembler code for function main(): 
0x0000000000400544 <main()+0>: push %rbp 
0x0000000000400545 <main()+1>: mov %rsp,%rbp  
0x0000000000400548 <main()+4>: sub $0x10,%rsp 
0x000000000040054c <main()+8>: movl $0x87654321,-0x4(%rbp) 
0x0000000000400553 <main()+15>: callq 0x400528 <func()> 
0x0000000000400558 <main()+20>: add -0x4(%rbp),%eax 
0x000000000040055b <main()+23>: leaveq 
0x000000000040055c <main()+24>: retq 
End of assembler dump. 
(gdb) disass func 
Dump of assembler code for function func(): 
0x0000000000400528 <func()+0>: push %rbp 
0x0000000000400529 <func()+1>: mov %rsp,%rbp 
0x000000000040052c <func()+4>: movl $0x12345678,-0xc(%rbp) <=how -0xc comes? 
0x0000000000400533 <func()+11>: lea -0xc(%rbp),%rax 
0x0000000000400537 <func()+15>: mov %rax,-0x8(%rbp) 
0x000000000040053b <func()+19>: mov -0x8(%rbp),%rax 
0x000000000040053f <func()+23>: mov (%rax),%eax 
0x0000000000400541 <func()+25>: leaveq 
0x0000000000400542 <func()+26>: retq 
End of assembler dump. 

mia domanda è come 0xc nel seguente riga

"0x000000000040052c <func()+4>: movl $0x12345678,-0xc(%rbp)" comes. 

mia comprensione è: 0x12345678 occupa 4 byte per la variabile a, seguito da 4 byte per il puntatore p, a cosa servono i restanti 4 byte?

Grazie.

EDIT:

Linux 2.6.18-194.el5 #1 SMP Tue Mar 16 21:52:39 EDT 2010 x86_64 

EDIT 1 :: Ancora una domanda: qual è la seguente riga per?

cassone del codice assemblatore per la funzione main():

0x0000000000400544 <main()+0>: push %rbp 
0x0000000000400545 <main()+1>: mov %rsp,%rbp  
0x0000000000400548 <main()+4>: sub $0x10,%rsp <== ? 

EDIT 2: Perché main() è necessario per allineare con 16 byte (da "sub $ 0x10,% RSP") mentre func not (0x0c non è allineato, vero?)?

+0

guarda la macchina è di 64 bit e l'indirizzo nella vostra macchina è di 8 byte 4 byte non –

+0

Sì, grazie mille. –

risposta

10

Linux 2.6.18-194.el5 # 1 SMP mar 16 mar 21:52:39 EDT 2010 x86_64

... seguito da 4 byte per puntatore "p" .. .

sei su un'architettura a 64 bit, quindi un puntatore occupa 64 bit = 8 byte:

#include <stdio.h> 

int main() { 
    int a = 0x12345678; 
    int *p = &a; 

    printf("%zu\n", sizeof(p)); 
    printf("%zu\n", sizeof(a)); 

    return 0; 
} 
$ gcc -std=c99 -Wall -pedantic -o sample sample.c 
$ ./sample 
8 
4 

analisi pila dettagliata:

Entrando func(), dopo l'esecuzione delle prime due istruzioni, lo stack è simile a questo (supposto che ogni rettangolo è 4 byte di memoria):

0x0000000000400528 <func()+0>: push %rbp 
0x0000000000400529 <func()+1>: mov %rsp,%rbp 
+..........+ 
| RET ADDR | (from CALL) 
+----------+ 
|RBP (high)| 
+..........| 
|RBP (low) | <== RSP, RBP 
+----------+ 
|   | <== -0x4(%rbp) -\ 
+..........+     \__ int *p 
|   | <== -0x8(%rbp) /
+----------+    -/ 
|   | <== -0xc(%rbp)  int a 
+----------+ 

Lei vengono poi memorizzare un valore nel locale a variabile:

0x000000000040052c <func()+4>: movl $0x12345678,-0xc(%rbp) <=how -0xc comes? 
+..........+ 
| RET ADDR | (from CALL) 
+----------+ 
|RBP (high)| 
+..........| 
|RBP (low) | <== RSP, RBP 
+----------+ 
|   | <== -0x4(%rbp) -\ 
+..........+     \__ int *p 
|   | <== -0x8(%rbp) /
+----------+    -/ 
|0x12345678| <== -0xc(%rbp)  int a 
+----------+ 

allora, siete sto suonare un puntatore a 64 bit nella variabile p:

0x0000000000400533 <func()+11>: lea -0xc(%rbp),%rax ; load address of a into RAX 
0x0000000000400537 <func()+15>: mov %rax,-0x8(%rbp) ; store address into pointer (64 bit) 
+..........+ 
| RET ADDR | (from CALL) 
+----------+ 
|RBP (high)| 
+..........| 
|RBP (low) | <== RSP, RBP 
+----------+ 
| &a (high)| <== -0x4(%rbp) -\ 
+..........+     \__ int *p 
| &a (low) | <== -0x8(%rbp) /
+----------+    -/ 
|0x12345678| <== -0xc(%rbp)  int a 
+----------+ 
+0

Ho scelto, OP ha dato una risposta in questione! –

+1

Sì, buona fortuna ha pubblicato il nome dell'arco :) –

+0

Avviso in main(): 'movl $ 0x87654321, -0x4 (% rbp)' suo '4' byte. ..come disassemblaggio di main() e func() può essere diverso –