这是我的x86汇编代码:
section .data
output db '%d',10,0
section .text
global main
extern printf
main :
xor ecx,ecx
xor eax,eax
mov eax,1
mov ecx,5
lable1:
push ecx
push eax
cmp eax,0
jg print
pop eax
pop ecx
inc eax
loop lable1
ret
print:
push eax
push output
call printf
add esp,8
ret
此程序应打印1到5之间的所有数字。 打印'1'后,为什么会出现分段错误?
答案 0 :(得分:4)
print
以ret
指令结束,这意味着您应该call
。因此,jg print
应为jng skip
/ call print
/ skip:
(或仅call print
,因为> 0
检查似乎不必要。)
call
将返回地址放在堆栈上,jg
没有。
答案 1 :(得分:1)
你不断出错的原因是:你忽略了堆栈!
您的lable1
子例程已正确设置,但是您的jg
从中弹出而忽略了堆栈 - 使堆栈损坏。
lable1:
push ecx
push eax
cmp eax,0
jg print
pop eax
pop ecx
inc eax
你
xor eax,eax ; EAX = 0 - breaking pipeline
mov eax,1 ; EAX = 1 - which is redundant
但是因为你的
cmp eax,0
jg print
在lable1
子例程中,如果EAX大于print:
(并且它是在EAX = 1的第一次迭代中),则跳转到0
例程,堆栈偏移量为由
-8
push ecx
push eax
在lable1:
的开头。来自ret
的{{1}} ting会在print:
末尾正确清理堆栈,这会导致程序返回到堆栈的第一个条目的地址,你有主要分配给[ESP] =(前EAX = 1):add esp,8
。
因此你得到一个mov eax,1
,因为你试图跳转/返回地址[00000001](= EAX = 1,32bit)。