【问题标题】:How to fix "Unhandled exception" error in assembly?如何修复程序集中的“未处理的异常”错误?
【发布时间】:2019-05-07 18:35:31
【问题描述】:

我编写了一个函数来确定一个值是素数还是非素数。但是当我从函数返回时,它会出现错误。
错误信息是

Project.exe 中 0x00000001 处的未处理异常:0xC0000005:访问冲突执行位置 0x00000001。

这个函数应该返回eax

        push ebp
        mov ebp, esp
        mov eax, [ebp+8]                ; store input value
        mov ecx, [ebp+8]                ; store input value in counter
        sub esp, 4                      ; local variable 
        sub ecx, 1                      ; avoid compare with itself
        cmp eax, 3                      ; compare with 1, 2, 3
        jbe Prime

    L1:
        cmp ecx, 3                      ; when count=3 to stop
        je NotP
        mov edx, 0                      ; clear edx to save remainder
        mov [esp-4], eax                ; save input value
        div ecx                         ; divide number
        cmp edx, 0                      ; check remainder
        je NotP                         ; if remainder=0 then not prime
        jmp Prime
        loop L1
    NotP:
        mov eax, 0
        push eax                        ; if delete this ilne still come up error
        pop ebp
        ret
    Prime:
        mov eax, 1                      
        push eax                        ; if delete this ilne still come up error
        pop ebp
        ret
    isPrime  endp

【问题讨论】:

  • 什么错误?将其包含在您的帖子中。编辑:函数 Epilog 之前的 push eax 指令是可疑的。如果省略那行会发生什么?
  • 导致异常的参数有哪些?
  • 我省略了那行仍然会出现同样的错误。
  • 您没有正确清理堆栈(即您的 Epilog 代码错误)。除了去掉push eax,还需要restore esp,否则就是“返回”到本地变量中的值了。

标签: function assembly x86 primes masm


【解决方案1】:
   mov [esp-4], eax                ; save input value

如果你打算使用你预留空间的局部变量,那么你必须写:

    mov [esp], eax                ; save input value

或者写成:

    mov [ebp-4], eax              ; save input value

正确的序言/结语应该是:

    push    ebp
    mov     ebp, esp
    sub     esp, 4                 ; local variable 
    mov     eax, [ebp+8]           ; store input value

    ...

NotP:
    mov     eax, 0
    pop     ebp                    ; remove local variable
    pop     ebp
    ret
Prime:
    mov     eax, 1                      
    pop     ebp                    ; remove local variable
    pop     ebp
    ret
isPrime  endp

    cmp edx, 0                      ; check remainder
    je NotP                         ; if remainder=0 then not prime
    jmp Prime
    loop L1

找到不为零的余数不足以得出该数是素数的结论!需要更多的测试。目前,loop L1 指令永远不会执行。
例如要测试 15,您的第一个除法是 15 / 14,这会产生非零余数,但 15 不是素数。

L1:
    cmp ecx, 3                      ; when count=3 to stop
    je NotP

循环的顶部也不正确!考虑测试数字 7。
第一次除法是 7 / 6 并且有余数所以循环必须继续
第二除法是 7 / 5 并且有余数,所以循环必须继续
第三次除法是 7 / 4 并且有余数,所以循环必须继续
您不再尝试除法并得出“非质数”结论,但 7 绝对是质数。

【讨论】:

  • pop ebp 真的是删除局部变量的最佳方法吗?修改 2 个寄存器并执行内存读取。如果您需要多于(或少于)1 个本地 int,它也无法正常工作。 mov esp, ebp 怎么样?
  • @DavidWohlferd 由于素数算法已经非常低效,我根本没有关注效率。 “先让它工作,然后让它更好” 关于本地整数的数量:如果小于 1(所以没有),为什么还要费心加载ESP
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
  • 2015-03-29
  • 2016-03-06
  • 1970-01-01
相关资源
最近更新 更多