Assemblage X86 – Gestion de l’instruction IDIV

J’écris actuellement un compilateur C simple, qui prend un fichier .c en entrée et génère un code assembleur (syntaxe X86, AT & T). Tout va bien, mais lorsque j’essaie d’exécuter une instruction IDIVQ, une exception en virgule flottante apparaît. Voici ma consortingbution:

int mymain(int x){ int d; int e; d = 3; e = 6 / d; return e; } 

Et voici mon code généré:

 mymain: .LFB1: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 movq %rdi, -40(%rbp) movq $3, -8(%rbp) movq $6, %rax movq -8(%rbp), %rdx movq %rdx, %rbx idivq %rbx movq %rax, -16(%rbp) movq -16(%rbp), %rax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE1: .size mymain, .-mymain 

Selon http://www.cs.virginia.edu/~evans/cs216/guides/x86.html , idivq% rbx devrait produire 6 / d (le quotient) en % rax . Mais je reçois une exception en virgule flottante et je n’arrive pas à trouver le problème.

Toute aide sera très appréciée!

    La première partie de la réponse de Mysticials est correcte, idiv effectue une division de 128/64 bits. La valeur de rdx , qui contient le bit 64 supérieur du dividende, ne doit donc pas contenir de valeur aléatoire. Mais une extension zéro est la mauvaise façon de faire.

    Comme vous avez des variables signées , vous devez vous connecter à rdx:rax rax en rdx:rax . Il existe une instruction spécifique pour cela, cqto ( convertir quad en oct ) dans AT & T et cqo en syntaxe Intel. Autant que je sache, les nouvelles versions de gas acceptent les deux noms.

     movq %rdx, %rbx cqto # sign extend rax to rdx:rax idivq %rbx 

    L’instruction idivq divise un entier de 128 bits ( rdx:rax ) par l’opérande.

    • rax détient les 64 bits les plus bas du dividende.
    • rdx contient les 64 bits supérieurs du dividende.

    Lorsque le quotient ne correspond pas à 64 bits, il lève cette exception de virgule flottante.

    Donc, ce que vous devez faire est de zéro rdx :

     movq %rdx, %rbx xorq %rdx, %rdx # zero "rdx" idivq %rbx 

    Si vous avez affaire à des entiers signés, vous devez également signer les extensions rax à rdx:rax , ce qui signifie que le rax signe rax être copié dans chaque bit de rdx et est réalisé avec cqo alias cqto:

     movq %rdx, %rbx cqo idivq %rbx