Le faux bug de l'an -4 avant la fin du monde -> pop [esp]
Par Baboon le mardi, novembre 25 2008, 21:52 - Lien permanent
juste un mini post pour vous faire part de mon effarement face à une bizarerie intelienne
A votre avis qu'est censé faire pop [esp] ?
Vous allez me dire : "ba facile ca ajoute juste 4 à esp et pis voila rien n'est modifié en mémoire easy quoi"
EH BIEN NON BANDES DE MALHEUREUX !!!
Pas avec le super da leet baboon's CPU en effet :
pile avant le pop [esp] 00000000 00000001 <- esp pointe sur le 1 00000002 00000003
on execute le pop [esp] .... et on se retrouve avec cette pile :
pile apres le pop [esp] 00000000 00000001 00000001 <- esp pointe sur le 2eme 1 ... HEIN ? quel 2eme 1 ?! 00000003
on voit bien que le 2 a été ecrasé par le 1 pointé par esp,en gros il nous a fait un pop [esp+4] le cochon !!
Pourtant si on lit le man intel on voit :
IF StackAddrSize = 32 THEN IF OperandSize = 32 THEN DEST ← SS:ESP; (* Copy a doubleword *) ESP ← ESP + 4; ELSE (* OperandSize = 16*) DEST ← SS:ESP; (* Copy a word *) ESP ← ESP + 2; FI; ELSE IF StackAddrSize = 64 THEN IF OperandSize = 64 THEN DEST ← SS:RSP; (* Copy quadword *) RSP ← RSP + 8; ELSE (* OperandSize = 16*) DEST ← SS:RSP; (* Copy a word *) RSP ← RSP + 2; FI; FI; ELSE StackAddrSize = 16 THEN IF OperandSize = 16 THEN DEST ← SS:SP; (* Copy a word *) SP ← SP + 2; ELSE (* OperandSize = 32 *) DEST ← SS:SP; (* Copy a doubleword *) SP ← SP + 4; FI; FI;
on a bien ESP ← ESP + 4; APRES le DEST ← SS:ESP;
J'en viens donc à ma question : WTFBBQ ?!
Après enquete le CPU d'ivanlef0u est aussi touché, serait ce le prémice d'une épidémie mondiale ? le bug de l'an - 4 avant la fin du monde ?
j'en sais foutrement rien ...
[EDIT] bon j'ai trouvé l'explication en lisant un peu mieux les man intels on y lit en effet :
If the ESP register is used as a base register for addressing a destination operand in memory, the POP instruction computes the effective address of the operand after it increments the ESP register. For the case of a 16-bit stack where ESP wraps to 0H as a result of the POP instruction, the resulting location of the memory write is processor-family-specific. The POP ESP instruction increments the stack pointer (ESP) before data at the old top of stack is written into the destination.
Ca n'explique quand même pas pourquoi ils ont ecrit un "faux" code sur le fonctionnement de l'instruction ...
Commentaires
Énorme
On panique, on panique, mais la solution est souvent dans les docs... Le plus difficile étant de savoir où
on panique pas tant que ça. La réponse que baboon a trouvé n'est pas satisfaisante non plus. Si on traduit ce qu'ils annoncent :
ESP <- ESP + 4
DEST <- [ESP] .... sauf que ESP a changé normalement mais en fait, le cpu utilise la valeur de esp avant le esp+4.
Perso, je pense (sans pouvoir le prouver) que la valeur à poper est mise en cache pendant la deuxième opération "esp += 4" ce qui permet d'avoir un comportement cohérent :
1) mise en cache de la valeur située en esp
2) esp += 4
3) affecter la valeur mise en cache au registre ou à l'espace mémoire de destination.
par exemple, sur mon petit ému, j'ai émulé cette instruction de cette façon :
émulation de pop DWORD PTR [esp] :
add ESP_, 4
call MOD_RM (edi <= ESP_)
mov esi, ESP_
mov eax, dword ptr [esi-4]
mov dword ptr [edi], eax
C'est en effet la meilleur chose à faire bea je ne comprends donc pas pourquoi ce n'est pas ce qui est expliqué dans la doc ...
étant donné que cette "représentation" marche pour tout les pop quelqu'ils soient ..
Une "correction" pourrait donc être :
bref, sont bizard chez intel quand même :p
tu as raison, la doc mériterait d'être corrigée. Le pire, c'est que la doc AMD n'est pas plus clair sur le sujet. Faudrait demander à sandpile pour en savoir plus.
Si j'ai bonne mémoire, je crois que c'était d'ailleurs une des manières de différencier un 286 d'un 386+, les 286 décrémentant *après* le mov, alors que les 386 et + *avant* comme tu l'as remarqué.