2009-06-11 6 views
9

J'ai récemment besoin de déboguer un programme au niveau de l'assemblage. Je n'ai pas beaucoup d'expérience en assembleur, donc je me suis dit que j'écrirais quelques programmes C simples et que je les utiliserais en une seule étape pour avoir une idée de la langue avant de débuter le débogage du code des autres. Cependant, je ne comprends vraiment pas ce que gcc fait de ces deux lignes (compilé avec -O0 -ggdb):Comment fonctionne cet ensemble de montage?

items[tail] = i; 
tail = (tail+1) % MAX_SIZE; 

où MAX_SIZE est #defined être 5 et i est une variable locale (stockée dans 0x8 (% ebp), je suppose). Selon gdb, cela devient:

0x08048394 <queue+17>: mov 0x8049634,%edx 
0x0804839a <queue+23>: mov 0x8(%ebp),%eax 
0x0804839d <queue+26>: mov %eax,0x804963c(,%edx,4) 
0x080483a4 <queue+33>: mov 0x8049634,%eax 
0x080483a9 <queue+38>: lea 0x1(%eax),%ecx 
0x080483ac <queue+41>: movl $0x66666667,-0xc(%ebp) 
0x080483b3 <queue+48>: mov -0xc(%ebp),%eax 
0x080483b6 <queue+51>: imul %ecx 
0x080483b8 <queue+53>: sar %edx 
0x080483ba <queue+55>: mov %ecx,%eax 
0x080483bc <queue+57>: sar $0x1f,%eax 
0x080483bf <queue+60>: mov %edx,%ebx 
0x080483c1 <queue+62>: sub %eax,%ebx 
0x080483c3 <queue+64>: mov %ebx,-0x8(%ebp) 
0x080483c6 <queue+67>: mov -0x8(%ebp),%eax 
0x080483c9 <queue+70>: shl $0x2,%eax 
0x080483cc <queue+73>: add -0x8(%ebp),%eax 
0x080483cf <queue+76>: mov %ecx,%edx 
0x080483d1 <queue+78>: sub %eax,%edx 
0x080483d3 <queue+80>: mov %edx,-0x8(%ebp) 
0x080483d6 <queue+83>: mov -0x8(%ebp),%ebx 
0x080483d9 <queue+86>: mov %ebx,0x804963 

Depuis 0x804963c est l'adresse des éléments, je peux voir comment la première ligne de code C fonctionne. En outre, 0x8049634 est l'adresse de tail, donc je suppose que queue + 33 et queue + 38 sont équivalents à% ecx = tail + 1 ... mais je n'ai aucune idée de ce qui se passe après. Qui aurait pensé qu'un simple modulo pourrait être aussi compliqué?

Répondre

14

C'est une façon d'éviter d'avoir à faire une instruction de division plus coûteuse. J'étais aussi très perplexe la première fois que j'ai rencontré ça. La chose amusante est que la recherche des nombres magiques qui sont utilisés pour cette astuce (dans ce cas, 0x66666667) donne souvent des résultats expliquant cette astuce. (Je crois à l'époque c'était la seule chose concrète que je devais faire parce que je n'avais pas les sources.)

Une recherche rapide m'a donné cet article de blog: http://blog.dkbza.org/2007/09/reverse-engineering-compiler-produced.html Il a quelques liens utiles en bas (y compris un lien indirect à un document sur cette astuce).

Questions connexes