idiv溢出异常asm

时间:2014-07-10 09:19:31

标签: assembly x86 nasm

在C C ++之前,我对装配很新 我试图创建一个简单的应用程序,将所有素数从2打印到给定的输入
当我跑步时,它会崩溃,这是正常的。看着OllyDbg,有罪的是:

move eax, ebx
idiv ecx ; !!! here

奇怪的是因为ecx不是0
值是EAX = 0000 0004,ECX = 0000 0002,它说我是Integer_Overflow(例外C000 0095)
如何在分裂期间有溢出?两个操作数均为32位
完成代码和ollydbg的截图

%include "asm_io.inc"

segment .data
input_msg   db  "Insert a number: ", 0
output_msg  db  "This is prime: ", 0

segment .bss
input       resd    1

segment .text
global _asm_main

; input => input number
; ebx => current number to execute [2 .. input]
; ecx => counter from 2 to current [2 .. current]

_asm_main:
    mov eax, input_msg
    call print_string

    call read_int
    inc eax
    mov [input], eax
    call print_nl

    mov ebx, 2h

    _start_main_loop:
        mov eax, [input] ; if current > input
        cmp eax, ebx
        jz _end_main_loop       

        mov ecx, 2h

        _iteration:
            cmp ebx, ecx
            je _print_number

            mov eax, ebx
            idiv ecx ; unsigned division?

            cmp edx, 0 ; if rem != 0 jmp
            jne _end_iteration
            inc ecx ; else inc ecx and re-divide
            jmp _iteration

        _print_number:
            mov eax, output_msg
            call print_string
            mov eax, ebx
            call print_int
            call print_nl

        _end_iteration:
            inc ebx

            jmp _start_main_loop

    _end_main_loop:

    popa
    mov     eax, 0
    leave
    ret

enter image description here

1 个答案:

答案 0 :(得分:2)

当n位除法的结果不能适合n位寄存器时,会发生idiv指令的整数溢出异常。这是可能的,因为idivdiv划分了整个寄存器对EDX:EAX。您的EDX值为1,您将EDX:EAX除以2,这会导致向右移位。此移位会在1的MSB上移动EAX,并且您的结果0x800000000x7FFFFFFF更强,根据documentation,这是非法的。

你可能会问自己“为什么会有这样的限制?”。它就在那里,因为EAX中的负值(MSB集)不是两个正整数除法的有效结果。

此问题的一般解决方案是在无符号除法之前将EDX的内容归零

mov eax, ebx
xor edx, edx
div ecx ;unsigned division

...或者签署扩展EAX(如果你期望负输入,你不应该没有负整数可以是素数)。

mov eax, ebx
cdq 
idiv ecx ;signed division