2017-01-27 2 views
3

Je suis toujours aux prises avec l'assembleur en ligne g ++ et j'essaie de comprendre comment l'utiliser.Essayer de comprendre le code simple désassemblé de g ++

J'ai adapté un morceau de code ici: http://asm.sourceforge.net/articles/linasm.html (Cité de la section "Instructions Assembleur avec C Expressions Opérandes" dans les fichiers d'information gcc)

static inline uint32_t sum0() { 
    uint32_t foo = 1, bar=2; 
    uint32_t ret; 
    __asm__ __volatile__ (
     "add %%ebx,%%eax" 
     : "=eax"(ret)    // ouput 
     : "eax"(foo), "ebx"(bar) // input 
     : "eax"     // modify 
    ); 
    return ret; 
} 

J'ai compilé Optimisations invalidantes:

g++ -Og -O0 inline1.cpp -o test 

Le code désassemblé me ​​déconcerte:

(gdb) disassemble sum0 
Dump of assembler code for function sum0(): 
    0x00000000000009de <+0>: push %rbp     ;prologue... 
    0x00000000000009df <+1>: mov %rsp,%rbp    ;prologue... 
    0x00000000000009e2 <+4>: movl $0x1,-0xc(%rbp)  ;initialize foo 
    0x00000000000009e9 <+11>: movl $0x2,-0x8(%rbp)  ;initialize bar 
    0x00000000000009f0 <+18>: mov -0xc(%rbp),%edx  ; 
    0x00000000000009f3 <+21>: mov -0x8(%rbp),%ecx  ; 
    0x00000000000009f6 <+24>: mov %edx,-0x14(%rbp)  ; This is unexpected 
    0x00000000000009f9 <+27>: movd -0x14(%rbp),%xmm1  ; why moving variables 
    0x00000000000009fe <+32>: mov %ecx,-0x14(%rbp)  ; to extended registers? 
    0x0000000000000a01 <+35>: movd -0x14(%rbp),%xmm2  ; 
    0x0000000000000a06 <+40>: add %ebx,%eax    ; add (as expected) 
    0x0000000000000a08 <+42>: movd %xmm0,%edx   ; copying the wrong result to ret 
    0x0000000000000a0c <+46>: mov %edx,-0x4(%rbp)  ; "  " "  "  " " 
    0x0000000000000a0f <+49>: mov -0x4(%rbp),%eax  ; "  " "  "  " " 
    0x0000000000000a12 <+52>: pop %rbp     ; 
    0x0000000000000a13 <+53>: retq 
End of assembler dump. 

Comme prévu, la fonction sum0() renvoie la mauvaise valeur.

Des pensées? Que se passe-t-il? Comment faire les choses correctement?

- EDIT - Sur la base de commentaires @MarcGlisse, j'ai essayé:

static inline uint32_t sum0() { 
    uint32_t foo = 1, bar=2; 
    uint32_t ret; 
    __asm__ __volatile__ (
     "add %%ebx,%%eax" 
     : "=a"(ret)    // ouput 
     : "a"(foo), "b"(bar)  // input 
     : "eax"     // modify 
    ); 
    return ret; 
} 

Il semble que le tutoriel, j'ai suivi est trompeur. "eax" dans le champ de sortie/entrée ne signifie pas le registre lui-même, mais e, a, x abréviations sur la table abbrev.

De toute façon, je ne comprends toujours pas. Le code ci-dessus entraîne une erreur de compilation: l'opérande 'asm' a des contraintes impossibles.

Je ne vois pas pourquoi.

+0

Activer les optimisations pourrait rendre la chose plus facile à comprendre? –

+0

"eax" ne signifie pas ce que vous pensez qu'il fait, vous voulez "un". Et pas besoin de marquer les sorties comme clobées. –

+1

S'il vous plaît lire plus attentivement: "pas besoin de marquer les sorties comme clobber". –

Répondre

2

Les contraintes d'assemblage en ligne étendues pour x86 sont répertoriées dans official documentation.
Le complete documentation vaut également la peine d'être lu.

Comme vous pouvez le voir, les contraintes sont toutes des lettres simples.
La contrainte « EAX » fo foo spécifie trois contraintes:

a
   The a register.

x
   Any SSE register.

e
   32-bit signed integer constant, or ...

Puisque vous dites que GCC eax est mis à mal, il ne peut pas mettre l'opérande d'entrée et il capte xmm0.

When the compiler selects the registers to use to represent the input operands, it does not use any of the clobbered registers

proper constraint is simply "a".
Vous devez supprimer eax (en passant, il devrait être rax en raison de la mise à zéro des bits supérieurs) des clobbers (et ajouter "cc").

+0

Merci! J'ai édité la question pour montrer le code résultant – Chocksmith

+0

@Chocksmith Glad pour aider. Vous éditez, cependant, est redondant car marquer ma réponse comme accepté est tout ce qui est nécessaire pour communiquer qu'il a résolu votre problème. Je recule votre édition pour la rendre conforme aux directives de l'OS :) Elle aidera également les futurs lecteurs ayant le même problème –