fpu ia-32, исключение с плавающей точкой

Я изучаю ia-32, и на 32-битной Ubuntu все шло нормально, но я перешел на 64-битную и начал использовать флаг -m32, и теперь я не могу использовать DIV где угодно, независимо от содержимого регистров, это дает мне всегда Исключение с плавающей точкой... И я уверен, что я не делю на ноль. Я использую GCC и GDB.

Это самый близкий вопрос к моей проблеме: FPU IA-32 SIGFPE, Арифметическое исключение

Я пытался поставить инструкцию fldcw с 0x220, но без разницы.

Мой исходный код:

.section .text 

Division:
    .int 0x220

str: 
    .asciz "%d"

.global binario             # void binario(int)

binario:
    pushl %ebp          # prologo
    movl %esp,%ebp          # 

    finit
    fldcw Division

    pushl %ebx
    pushl %ecx
    pushl %edx

    movl 8(%ebp),%eax       # param x to eax

    cmpl $0,%eax            # compare x with 0
    je fim              # return recursive call

    movl $2,%ecx            # prepare division
    divl %ecx           # divide eax with 2

    movl $0,%ecx            # clean ecx
    movb %al,%cl            # put division result on cl

    pushl %ecx          # push x/2
    call binario            # recursive call
    add $8,%esp         # clean esp

    movl $0,%ecx            # clean ecx
    movb %ah,%cl            # put division rest on cl

    pushl %ecx          # push division rest
    pushl $str          # push string
    call printf         # call printf function
    addl $8,%esp            # clean esp

fim:

    pushl %edx
    pushl %ecx
    pushl %ebx

    movl %ebp,%esp          # epilogo
    popl %ebp               #
    ret 

Журнал GDB:

28      divl %ecx           # divide eax with 2
2: $ecx = 2
1: $eax = 33
(gdb) 

Program received signal SIGFPE, Arithmetic exception.
binario () at ex08.s:28
28      divl %ecx           # divide eax with 2
2: $ecx = 2
1: $eax = 33

1 ответ

Решение

+1 для поиска SO и использования отладчика, -1 для не чтения ссылки на набор команд;)

div r/m32 Используемый вариант делит 64-битное количество, образованное из edx (верхние 32 бита) и eax (младшие 32 бита). Кроме того, вы также получите это исключение, если ваш результат выходит за пределы допустимого диапазона. Проблема в том, что вы не обнуляете edx таким образом, он имеет случайное значение, которое вызывает переполнение всего деления. Вам нужно очистить edx (Нуль-расширение eax) перед беззнаковым делением и подписать-продлить eax в edx перед подписанным делением.

PS: я надеюсь, что вы на самом деле не используете div делить на 2, Делить или умножать на степени 2 Вы должны использовать смены.

Другие вопросы по тегам