我是NASM汇编程序的新手,并试图编写自己的汇编代码。在编译时,我没有收到任何错误,但在运行时,代码崩溃。在调试时,似乎代码在push或_printf调用时崩溃。
我已经对我的代码进行了评论,使其更具可读性。
global _main
extern _printf
section .text
_main:
jp _loop ;jump to loop
_loop:
mov ebx, [a] ;move double word 'a' into register ebx
inc ebx ;increment register ebx
mov [a], ebx ;move contents of ebx into double word 'a'
add ebx, '0' ;add char 0 (0x30)
push ebx ;push ascii character on to stack
push format ;push format string on to stack
call _printf ;call print function
cmp dword [a], 10 ;compare if value of a is equal to 10
jne _loop ;loop if not equal to 10
ret ;return if equal to 10
a:
dd 0 ;initialize dword as 0
format:
db "%i", 0 ;format string for printf
提前致谢!我希望这不是太高兴。
答案 0 :(得分:2)
我自己尝试编译和运行代码(唉,不在Windows上;谁说程序集不可移植?),而且它不是在call _printf
或push
行上崩溃,而是在{{{ 1}}。 mov [a], ebx
段的权限是读取和执行,但不是写入。 .text
位于a
,.text
尝试写入mov [a], ebx
,因此它会尝试写入不可写的部分,程序崩溃时会出现一般性保护错误。解决这个问题的方法是将a
放在不同的部分,例如a
。
这应该解决你的(第一个)问题,但还有两件事你应该知道:
您有.data
作为jp _loop
的第一条指令。如果设置了奇偶校验标志,则跳转到_main
。我认为你实际上并不打算测试奇偶校验标志;在这种情况下,它要么跳转,要么测试失败,无论如何它都会落到_loop
。你可以做一个明确的_loop
,但实际上没有必要。如果我是你,我会完全省略该指示,jmp
和_main
重合。
我相信_loop
使用C调用约定,调用者负责弹出参数(与用于Windows API函数的stdcall不同);你把很多东西都推到了堆栈上,从不弹出它们。这意味着您执行的迭代次数越多,您使用的堆栈内存就越多。这似乎不是你想要的。此外,您稍后_printf
,由于您在同一时间推送东西,因为堆栈顶部不是返回地址,因此不会返回正确的位置。您需要在调用ret
后显式弹出或调整堆栈指针:
_printf
可替换地:
在循环之前,保留适当的堆栈空间:
add esp, 8
循环后,释放堆栈空间:
sub esp, 8
不是推送参数,而是修改堆栈中已有的数据:
add esp, 8