2017-05-02 3 views
2

J'ai récemment tombé sur un code de compilateur intéressant que je ne comprends pas. Prenez le code suivant:curieux code de compilateur gcc pour x | = 128 quand x est uint8

unsigned char x; 
... 
x |= 127; 
x |= 128; 

Pour la première instruction, le compilateur génère:

or eax, 0x7f. 

Cependant, pour la deuxième déclaration, il devient:

or eax, 0xffffff80 

Il semble que pour valeurs inférieures à 127, des valeurs d'un octet sont utilisées alors qu'après 128 dword sont préférées.

Quelqu'un a-t-il une idée de ce qui se passe? J'ai reproduit ce gcc 6.2 (plus tard je pense).

J'ai essayé de poster sur les listes de diffusion gcc ([email protected] ou [email protected]) mais j'ai seulement eu des échecs de livraison.

+6

Je suppose que c'est juste un artefact de la façon dont votre désassembleur formate les nombres ('0x80' est négatif s'il est interprété comme un nombre signé). –

+0

J'utilise gdb. Voici comment il imprime les valeurs dans la console https://pastebin.com/0A2SXUNU –

+0

J'ai également compilé le code avec -S et j'ai obtenu ceci: https://pastebin.com/g8aSn9iy –

Répondre

5

Les deux instructions sont 3 octets de large ainsi qu'il ressort de la sortie de démontage:

83 c8 7f    or  $0x7f,%eax 
83 c8 80    or  $0xffffff80,%eax 

Le 83/1 est 32-bit register/memory with 8-bit sign-extended immediate value:

83 /1 ib OR r/m32,imm8 r/m32 OR imm8 (sign-extended). 

Ainsi, en effet, il ne changer la non partie visible du registre 32 bits, mais cela n'a pas d'importance. Ce n'est pas moins efficace que toute autre méthode. Le signe non permet d'étendre la valeur immédiate de 8 bits, à l'exception de ceux qui fonctionnent avec des demi-registres/trimestres de 8 bits. Mais en utilisant cette instruction, il fonctionne de la même manière avec d'autres registres qui sont adressables avec r/m32 mais qui ne peuvent pas être accédés comme des octets individuels (edi, esi par exemple).

+0

Comment avez-vous généré les instructions d'assemblage sous cette forme? –

+1

compilé avec '-c' dans le fichier objet (j'ai un ordinateur 64 bits donc j'ai compilé avec -m32); puis vu depuis le fichier '.o' avec' objdump -d' –

+0

Ok donc la bonne nouvelle est que le code de l'assemblage est bon. Mais il serait intéressant de voir ce qui ne va pas dans la façon dont ils sont affichés. –