如何在汇编语言X86中设置溢出条件

时间:2012-03-22 01:33:49

标签: assembly x86

我有以下两个功能。 nCr计算int的阶乘。 nCr调用另一个函数,它是进行计算的阶乘。随着数字变大,存在溢出。我需要设置溢出条件。我正在尝试使用JO(跳过溢出),但是在编译时我遇到了问题。大胆是我提出条件的地方。如果有人可以帮助指出我的错误那将是伟大的!

_nCr:  
    pushl   %ebp  
    movl    %esp, %ebp  
    subl    $56, %esp  
    movl    8(%ebp), %eax  
    movl    %eax, (%esp)    

**

call      _factorial  

    cmp    $0, %eax
    je      L22
    cmpl    $0, %eax
    jne      L23
   L22: 
    movl $0, %eax
    leave 
    ret

**

    L23:
    movl    %eax, -12(%ebp)  
    movl    12(%ebp), %eax  
    addl    $1, %eax  
    movl    %eax, (%esp)  
    call    _factorial  
    movl    %eax, -16(%ebp)  
    movl    12(%ebp), %eax  
    notl    %eax  
    addl    8(%ebp), %eax  
    movl    %eax, (%esp)  
    call    _factorial  
    movl    %eax, -20(%ebp)  
    movl    -16(%ebp), %eax  
    movl    %eax, %edx  
    imull   -20(%ebp), %edx  
    movl    %edx, -28(%ebp)  
    movl    -12(%ebp), %eax  
    movl    %eax, %edx  
    sarl    $31, %edx  
    idivl   -28(%ebp)  
    leave  
    ret  

_factorial:  
    pushl   %ebp  
    movl    %esp, %ebp  
    subl    $16, %esp  
    movl    $1, -8(%ebp)  
    movl    $1, -4(%ebp)  
    jmp L3  
L4:   
    movl    -8(%ebp), %eax   

**

  

imull -4(%ebp),%eax
          jo L2

**

    movl    %eax, -8(%ebp)  
    addl    $1, -4(%ebp) 
L2:
   movl   $0, %eax
   leave
   ret**

L3:
    movl    -4(%ebp), %eax  
    cmpl    8(%ebp), %eax  
    jle L4  
    movl    -8(%ebp), %eax  
    leave  
    ret  

基本上如果检测到溢出,则函数应返回0.

1 个答案:

答案 0 :(得分:0)

首先,如果您的值被限制为32位,则使用循环进行阶乘是很奇怪的,因为阶乘(12)是最后一个适合32位的值。因此,将factorial实现为表查找1到12之间的值更简单,并为任何其他值返回0。

如果您仍然想要使用循环(好吧,它可以是作业要求),请注意放在%edx中的产品的大部分(通过imull)。它应等于%eax符号的扩展,否则产品不能适合32位。两个示例变体:

mov %eax, %ecx
sarl $31, $ecx
cmp %edx, %ecx
jne overflow_found

mov %edx, %ecx
cltd
cmp %edx, %ecx
jne overflow_found

我也很困惑你的程序数字溢出的地方。唯一可疑的地方是“idiv”,但只要%edx是%eax符号的扩展,如果除数为零,就会发生这种情况。你应该在调用divide之前显式检查divisor值,编译器和处理器都不会这样做。