make - Conjunto X86: manejo de la instrucción IDIV
lets make an interpreter (2)
Actualmente estoy escribiendo un compilador de C simple, que toma un archivo .c como entrada y genera código de ensamblado (sintaxis X86, AT & T). Todo es bueno, pero cuando trato de ejecutar una instrucción IDIVQ, obtengo una excepción de coma flotante. Aquí está mi entrada:
int mymain(int x){
int d;
int e;
d = 3;
e = 6 / d;
return e;
}
Y aquí está mi código generado:
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
De acuerdo con http://www.cs.virginia.edu/~evans/cs216/guides/x86.html , idivq% rbx debería producir 6 / d (el cociente) en % rax . Pero recibo una excepción de coma flotante, y parece que no puedo encontrar el problema.
¡Cualquier ayuda será muy apreciada!
La instrucción idivq
divide un entero de 128 bits ( rdx:rax
) por el operando.
-
rax
contiene los 64 bits más bajos del dividendo. -
rdx
contiene los 64 bits superiores del dividendo.
Cuando el cociente no se ajusta a 64 bits, arrojará esa excepción de coma flotante.
Entonces, lo que debes hacer es cero rdx
:
movq %rdx, %rbx
xorq %rdx, %rdx # zero "rdx"
idivq %rbx
Si está tratando con enteros con signo, también necesita firmar extender rax
a rdx:rax
, eso significa copiar el rax
signo de rax
a cada bit de rdx
y se logra con cqo alias cqto:
movq %rdx, %rbx
cqo
idivq %rbx
La primera parte de la respuesta de Mysticials es correcta, idiv
realiza una división de 128/64 bits, por lo que el valor de rdx
, que contiene los 64 bits superiores del dividendo, no debe contener un valor aleatorio. Pero una extensión cero es el camino equivocado por recorrer.
Como tiene variables firmadas , debe firmar extender rax
a rdx:rax
. Hay una instrucción específica para esto, cqto
( convertir quad a oct ) en AT & T y cqo
en sintaxis Intel. Las versiones más recientes de AFAIK de gas aceptan ambos nombres.
movq %rdx, %rbx
cqto # sign extend rax to rdx:rax
idivq %rbx