2011-10-18 3 views
1

Je copie ce code à partir d'un livre. Dans chaque commentaire, je mets un numéro, puis je vous pose la question (1,2,3,4) relative aux lignes de code commentées par ce nombre. J'espère que c'est ok.stack, esp register

1) ESP pointe vers ces valeurs de tampon. Pourquoi ne pas voir un 0x41 pour'A 'ici?

2) Les points ESP signalent la mémoire variable qui doit contenir 31337, soit 0x7a69 en hexadécimal. POURQUOI INDIQUE-T-ELLE CE NUMÉRO? 0xbffff89c ???

3) Pointe sur le pointeur de la pile précédente, qui est dans ce cas une adresse correcte.

4) Adresse de retour. Aussi correct.

5) Arguments. Corrigez également les valeurs.

Alors, que se passe-t-il en 1) et 2)? Est-ce le rembourrage?

Merci beaucoup.

void test_function(int a, int b, int c, int d) { 
    int flag; 
    char buffer[10]; 
    flag = 31337; 
    buffer[0] = 'A'; 
} 

int main() { 
    test_function(1, 2, 3, 4); 
} 


GDB debug session 
Breakpoint 2, test_function (a=1, b=2, c=3, d=4) at stack_example.c:5 
5 flag = 31337; 
(gdb) i r esp ebp eip 
esp 0xbffff7c0 0xbffff7c0 
ebp 0xbffff7e8 0xbffff7e8 
eip 0x804834a 0x804834a <test_function+6> 
(gdb) disass test_function 
Dump of assembler code for function test_function: 
0x08048344 <test_function+0>: push ebp 
0x08048345 <test_function+1>: mov ebp,esp 
0x08048347 <test_function+3>: sub esp,0x28 
0x0804834a <test_function+6>: mov DWORD PTR [ebp-12],0x7a69 
0x08048351 <test_function+13>: mov BYTE PTR [ebp-40],0x41 
0x08048355 <test_function+17>: leave 
0x08048356 <test_function+18>: ret 
End of assembler dump. 
(gdb) print $ebp-12 
$1 = (void *) 0xbffff7dc 
(gdb) print $ebp-40 
$2 = (void *) 0xbffff7c0 
    (gdb) x/16xw $esp 
    0xbffff7c0: 0x00000000 0x08049548 0xbffff7d8 0x08048249 // 1 
    0xbffff7d0: 0xb7f9f729 0xb7fd6ff4 0xbffff808 0x080483b9 // 1 
    0xbffff7e0: 0xb7fd6ff4         // 1 
    0xbffff89c            // 2 
    0xbffff808            // 3 
    0x0804838b            // 4 
    0xbffff7f0:            // 4 
    0x00000001 0x00000002 0x00000003 0x00000004    // 5 




[email protected]:~/booksrc $ gcc -g stack_example.c 
[email protected]:~/booksrc $ gdb -q ./a.out 
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1". 
(gdb) disass main 
Dump of assembler code for function main(): 
0x08048357 <main+0>: push ebp 
0x08048358 <main+1>: mov ebp,esp 
0x0804835a <main+3>: sub esp,0x18 
0x0804835d <main+6>: and esp,0xfffffff0 
0x08048360 <main+9>: mov eax,0x0 
0x08048365 <main+14>: sub esp,eax 
0x08048367 <main+16>: mov DWORD PTR [esp+12],0x4 
0x0804836f <main+24>: mov DWORD PTR [esp+8],0x3 
0x08048377 <main+32>: mov DWORD PTR [esp+4],0x2 
0x0804837f <main+40>: mov DWORD PTR [esp],0x1 
0x08048386 <main+47>: call 0x8048344 <test_function> 
0x0804838b <main+52>: leave 
0x0804838c <main+53>: ret 
End of assembler dump 
(gdb) disass test_function() 
Dump of assembler code for function test_function: 
0x08048344 <test_function+0>: push ebp 
0x08048345 <test_function+1>: mov ebp,esp 
0x08048347 <test_function+3>: sub esp,0x28 
0x0804834a <test_function+6>: mov DWORD PTR [ebp-12],0x7a69 
0x08048351 <test_function+13>: mov BYTE PTR [ebp-40],0x41 
0x08048355 <test_function+17>: leave 
0x08048356 <test_function+18>: ret 
End of assembler dump 
(gdb) 
+1

Où exactement avez-vous cassé l'exécution de votre code? – RedX

+0

Il est difficile de dire quoi que ce soit sans le code compilé. Un compilateur pourrait décider de ne pas stocker 'flag' et' buffer', car ils ne sont jamais lus. Veuillez inclure un démontage de 'test_function' et' main'. –

Répondre

5

'A' et 31337 sont littérales. Ils n'ont aucune raison d'être placés sur la pile.

Il serait plus intéressant pour vous si vous imprimiez un démontage de ce bloc de code pour voir exactement ce que le compilateur émet. Ensuite, vous pouvez effectuer une vérification croisée avec ce que contient votre pile à l'exécution. Etant donné que votre fonction n'a pas d'effets secondaires, elle peut être optimisée pour une opération non-op.

Voici ce que je reçois avec votre code dans un environnement que je suis plus familier avec:

Breakpoint 1, test_function (a=1, b=2, c=3, d=4) at t.c:4 
4  flag = 31337; 
(gdb) disass test_function 
Dump of assembler code for function test_function: 
    0x080483a4 <+0>: push %ebp 
    0x080483a5 <+1>: mov %esp,%ebp 
    0x080483a7 <+3>: sub $0x10,%esp 
=> 0x080483aa <+6>: movl $0x7a69,-0x4(%ebp) 
    0x080483b1 <+13>: movb $0x41,-0xe(%ebp) 
    0x080483b5 <+17>: leave 
    0x080483b6 <+18>: ret  
End of assembler dump. 
(gdb) display $ebp 
2: $ebp = (void *) 0xffffcd70 
(gdb) display $esp 
3: $esp = (void *) 0xffffcd60 
(gdb) x/16xw $esp 
0xffffcd60: 0xf7e7dcdd 0xf7fa7324 0xf7fa6ff4 0x00000000 
0xffffcd70: 0xffffcd88 0x080483e1 0x00000001 0x00000002 
0xffffcd80: 0x00000003 0x00000004 0xffffcdf8 0xf7e66cc6 
0xffffcd90: 0x00000001 0xffffce24 0xffffce2c 0x00000001 

différence avec votre cas, à l'exception de la syntaxe ASM, est que mon compilateur réservé moins de jeu sur la pile, mais c'est à peu près tout. Donc, comme dans votre cas, les littéraux se retrouvent dans le flux d'instructions , pas sur la pile. L'adresse de la pile et son contenu (interprété comme ints 32bit, prudent avec boutisme) des habitants:

(gdb) x/1xw $ebp-4 
0xffffcd6c: 0x00000000 
(gdb) x/1xw $ebp-0xe 
0xffffcd62: 0x7324f7e7 

permet maintenant attribuons à flag:

(gdb) n 
5  buffer[0] = 'A'; 
(gdb) x/8xw $esp 
0xffffcd60: 0xf7e7dcdd 0xf7fa7324 0xf7fa6ff4 0x00007a69 
0xffffcd70: 0xffffcd88 0x080483e1 0x00000001 0x00000002 
(gdb) x/1xw $ebp-4 
0xffffcd6c: 0x00007a69 
(gdb) x/1xw $ebp-0xe 
0xffffcd62: 0x7324f7e7 

Tout bien, la fente à droite de la pile a été mis à jour ($ebp-4 dernier emplacement 32 bits dans la ligne 1 du x/8xw).

et permet de définir le premier élément de buffer:

(gdb) n 
6 } 
(gdb) x/4x $ebp-0xe 
0xffffcd62: 0x41 0xf7 0x24 0x73 
(gdb) x/8xw $esp 
0xffffcd60: 0xf741dcdd 0xf7fa7324 0xf7fa6ff4 0x00007a69 
0xffffcd70: 0xffffcd88 0x080483e1 0x00000001 0x00000002 
(gdb) x/1xw $ebp-4 
0xffffcd6c: 0x00007a69 
(gdb) x/1xw $ebp-0xe 
0xffffcd62: 0x7324f741 

Tout bien à nouveau. L'endianness rend les choses un peu bizarres quand on les considère comme des octets 32 bits, mais cela semble bien si on les regarde octet par octet.

+0

Désolé, mais cette réponse n'a pas de sens. –

+0

Je pense que oui.La ligne 'flag = 31337;' avec GCC sur x86_64 est compilée en un 'mov' avec 31337 comme opérande immédiat. Il n'y a absolument aucune raison de voir ces constantes sur la pile. Si elles étaient des littéraux de chaîne (et n'avaient pas été optimisées), elles pourraient apparaître dans le désassemblage comme des pointeurs dans une zone constante en lecture seule. Pas besoin non plus de les mettre sur la pile, (à moins que le compilateur ne commence à jouer des tours amusants sur des machines affamées de registre peut-être). Le contenu de la pile sans le code d'assemblage correspondant est essentiellement inutile. – Mat

+0

Je pense qu'il voulait dire '.... sens pour moi' == Je ne comprends pas ... – gnometorule