在主要之前的装配中的Segfault

时间:2014-09-10 02:52:06

标签: assembly nasm

我正在编写此汇编代码以从命令行获取输入并打印出该输入的每个因子。使用NASM,我正在使用nasm -f win32 --prefix _ -o lab2.o lab2.sgcc lab2.o -o lab2进行编译。它每次运行时都会出现段错误和核心转储,即使我在主要的第一行放置ret,我也无法弄清楚它可能遇到问题的位置。请帮助我找到我失踪的东西。

global main
extern printf
extern atoi

section .data
    strFormat db "%d is a factor of %d\n",0

section .bss
    input: resb 64
    cdown: resb 64

section .text
    main:
        mov ebx, [esp+8]        ;ebx now points to the cmd arguments
        mov eax, [ebx+4]        ;eax now points to the correct argument
        push dword eax          ;esp now points to the same argument
        call atoi           ;esp now points an integer
        add esp, 4          ;returns esp after call
        mov dword [input], eax      ;input now points to that integer
        and edx, 0x00           ;edx is now cleared for use in div
        mov ebx, 2          ;ebx now points to 2
        div ebx             ;divides (edx:eax) by arg(ebx), with the remainder in (edx)
        mov [cdown], eax        ;countdown is lowered to this greatest factor
        jmp loop            ;proceeds to the "loop"
        ret

    loop:                   ;divides, checks, and decrements, before looping
        and edx, 0x00           ;clears the register edx for use in div
        mov eax, [input]        ;eax now points to the input integer
        mov ebx, [cdown]        ;ebx now points to the countdown
        div ebx             ;divides input by countdown, with the remainder in edx
        cmp edx, 0          ;if the remainder is zero...
        je fact             ;...jump to factor
        dec dword [cdown]       ;countdown counts down
        cmp dword [cdown], 0        ;if countdown is greater than zero...
        jg loop             ;...jump to the beginning of the loop
        ret

    fact:                   ;prints a factor
        push dword [input]      ;pushes the original integer into the string
        push dword [cdown]      ;pushes the factor into the string
        push strFormat
        call printf         ;prints the string format
        add esp, 12         ;returns esp after call
        jmp loop

2 个答案:

答案 0 :(得分:1)

如果我们将您的程序运行为:

 lab2.exe 12

在您的代码开始时,这就是Windows上的堆栈:

enter image description here

所以,之后:

mov ebx, [esp+8]

我们有ebx=00000000

然后[ebx+4]在阅读00000004时向您发送访问违规行为。这里有个大问题。

正如您在堆栈图像中看到的那样,如果您执行以下操作,则可以访问cmd参数:

mov eax, [esp+0Ch]

但在Windows中,您应该使用Win32 API:

GetCommandLine获取指向未解析的cmd行的指针。

CommandLineToArgvW将cmd行解析为参数数组。

请看这个例子:Getting command line arguments using the Win32 API

当然,这可能只是您代码的第一个问题。

答案 1 :(得分:0)

无论是什么,在我看来都是一些特定于Windows的错误,因为我可以在Linux上编译和运行它。 (它有其他错误,但它不会发生段错误。)

我无法帮助您使用Windows(因为我没有它),但考虑到这一点,您可能希望将调试工作集中在构建环境而不是您自己的源代码上。