我正在编写此汇编代码以从命令行获取输入并打印出该输入的每个因子。使用NASM,我正在使用nasm -f win32 --prefix _ -o lab2.o lab2.s
和gcc 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
答案 0 :(得分:1)
如果我们将您的程序运行为:
lab2.exe 12
在您的代码开始时,这就是Windows上的堆栈:
所以,之后:
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(因为我没有它),但考虑到这一点,您可能希望将调试工作集中在构建环境而不是您自己的源代码上。