比较值时出现分段错误

问题描述:

我是汇编新手,遇到了一个我不知道如何调试的问题。我正在编写一个非常简单的程序,它接受一个命令行参数,然后输出参数的因子。目的是熟悉决策和循环。到目前为止,我已经设法将它们整合在一起,并且它适用于偶数,但不适用于奇数。此外,它可能会为偶数产生正确的结果,但在最后一次检查后仍然会出现段错误。比较值时出现分段错误

 section .bss 
     input: resb 100 
     count: resb 100 


     main: 
       mov ecx,[esp+8]    ;point to command line arguement 
       mov eax,[ecx+4]    ;extract second element 


       push dword eax    ;segfaults without dword. 
       call atoi     ;convert the ascii from cmd line into integer. 
       add esp,4 
       mov dword [input],eax  ;copy original 

       xor edx, edx    ;zero out edx to prevent division error. [2] 
       mov ebx,2 
       div ebx      ;divide eax by ebx. quotient stored in eax, remainder stored in edx. 

       mov [count],eax    ;make a copy of the original argument/2, no number larger can be a factor. 

       jmp checkAgain 

     ret 

     ;strFormat db `Count: %d, Quotient: %d, Remainder: %d, Input: %d, EBX: %d\n`,0 

     true: 
       push ebx 
       push dword [input] 
       push edx 
       push eax 
       push dword [count] 

       push strFormat 
       call printf 
       add esp,16 
       cmp dword [count],0 
       jg checkAgain 
     ret 

     checkAgain: 

       xor edx,edx 
       mov eax,[input] 
       mov ebx,[count] 
       div ebx 
       dec dword [count] 
       cmp edx,0 
       je true 
       mov ecx,dword [count]  
       cmp ecx,0    ;this is where I expect the program to end, but it crashes. 
       jg checkAgain 
     ret 

大会对我来说很难绕过我的脑海;我有很多东西需要学习,所以我很欣赏任何反馈。

+0

我不能用你的代码产生奇数的错误结果。请添加一个数字,预期结果和实际结果。 – rkhb 2014-08-29 09:20:59

+0

我解释得不好。它不会产生不正确的结果,它会在程序结束时发生段错误。 – user2325881 2014-08-29 20:16:16

分段故障是由add esp,16造成的。您将6个dword(= 24个字节)推入堆栈,因此必须在call printfadd esp,24之后清除堆栈。

您的代码不可编译。这一次对我的作品:

; Name:  spagfac.asm 
; Assemble: nasm -felf32 spagfac.asm 
; Link:  gcc -m32 -o spagfac spagfac.o 
; Run:  ./spagfac 60 

global main 
extern atoi, printf 

section .bss 
    input: resb 100 
    count: resb 100 

section .data 
    strFormat db `Count: %d, Quotient: %d, Remainder: %d, Input: %d, EBX: %d\n`,0 

section .text 

    main: 
     mov ecx,[esp+8]   ;point to command line arguement 
     mov eax,[ecx+4]   ;extract second element 


     push dword eax   ;segfaults without dword. 
     call atoi    ;convert the ascii from cmd line into integer. 
     add esp,4 
     mov dword [input],eax ;copy original 

     xor edx, edx   ;zero out edx to prevent division error. [2] 
     mov ebx,2 
     div ebx     ;divide eax by ebx. quotient stored in eax, remainder stored in edx. 

     mov [count],eax   ;make a copy of the original argument/2, no number larger can be a factor. 

     jmp checkAgain 

    ret 

    true: 
     push ebx 
     push dword [input] 
     push edx 
     push eax 
     push dword [count] 

     push strFormat 
     call printf 
     add esp,24 
     cmp dword [count],0 
     jg checkAgain 
    ret 

    checkAgain: 

     xor edx,edx 
     mov eax,[input] 
     mov ebx,[count] 
     div ebx 
     dec dword [count] 
     cmp edx,0 
     je true 
     mov ecx,dword [count] 
     cmp ecx,0 
     jg checkAgain 
    ret 

“退出”与ret仅适用于GCC。如果使用LD,则必须使用系统调用(int 80h/fn 01h)退出。

+0

你对此绝对正确,我确实在堆栈中有错误的移动次数,但是,即使使用此修复程序,segfault仍会发生。 – user2325881 2014-08-29 20:14:53

+0

@ user2325881:我更正了您的代码并将其添加到了我的帖子中。也许你使用了错误的汇编器/编译器/链接器命令。 – rkhb 2014-08-29 21:07:57