Сборка X86 - Обработка инструкции IDIV
В настоящее время я пишу простой компилятор C, который принимает .c файл в качестве ввода и генерирует код сборки (синтаксис X86, AT & T).
Everyting хорошо, но когда я пытаюсь выполнить команду IDIVQ, я получаю исключение с плавающей запятой. Здесь мой ввод:
int mymain(int x){
int d;
int e;
d = 3;
e = 6 / d;
return e;
}
И вот мой сгенерированный код:
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
Согласно http://www.cs.virginia.edu/~evans/cs216/guides/x86.html, idivq% rbx должен произвести 6/d (коэффициент) в % rax. Но я получаю исключение с плавающей запятой, и я не могу найти проблему.
Любая помощь будет высоко оценена!
Ответы
Ответ 1
Первая часть ответа Mysticals верна, idiv
выполняет разделение 128/64 бит, поэтому значение rdx
, которое содержит верхний бит 64 из дивиденда, не должно содержать случайного значения. Но нулевое расширение - неправильный путь.
Поскольку вы подписали переменные, вам нужно подписать расширение rax
на rdx:rax
. Для этого есть специальная инструкция, cqto
(конвертировать quad в oct) в AT & T и cqo
в синтаксисе Intel. AFAIK более новые версии газа принимают оба названия.
movq %rdx, %rbx
cqto # sign extend rax to rdx:rax
idivq %rbx
Ответ 2
Команда idivq
делит 128-битное целое число (rdx:rax
) на операнд.
-
rax
содержит младшие 64-бит дивиденда.
-
rdx
содержит верхние 64-бит дивиденда.
Когда фактор не вписывается в 64-битные, он будет генерировать исключение с плавающей запятой.
Итак, вам нужно сделать нуль rdx
:
movq %rdx, %rbx
xorq %rdx, %rdx # zero "rdx"
idivq %rbx
Если вы имеете дело со значащими целыми числами, вам также нужно подписать расширение rax
на rdx:rax
, что означает копирование знака знака rax
в каждый бит rdx
и выполняется с помощью cqo alias cqto:
movq %rdx, %rbx
cqo
idivq %rbx