0

我正在学习 ia-32 并且在 32 位 Ubuntu 上一切正常,但是我切换到 64 位并开始使用标志 -m32 现在我无法在任何地方使用 DIV,无论寄存器的内容如何,​​它总是给我浮点异常...而且我确定我不会被零除。我正在使用 gcc 和 gdb。

这是最接近我的问题的问题:FPU IA-32 SIGFPE, Arithmetic exception

我试图将指令 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
4

1 回答 1

3

+1 用于搜索 SO 并使用调试器,-1 用于不读取指令集参考;)

您使用的div r/m32变体将 64 位数量除以edx(前 32 位)和eax(低 32 位)形成。此外,如果您的结果超出范围,您也会收到此异常。问题是你没有归零edx,所以它有一些随机值,导致整个除法溢出。您需要在无符号除法之前清除edx(零扩展eax),并在有符号除法之前进行符号eax扩展edx

PS:我希望你不是真的用div除以2。要除以或乘以2你的幂应该使用移位。

于 2014-11-13T13:50:46.787 回答