Подтвердить что ты не робот

Сборка 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. Но я получаю исключение с плавающей запятой, и я не могу найти проблему.

Любая помощь будет высоко оценена!

4b9b3361

Ответ 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