打印时为什么会出现分段故障?

时间:2016-04-08 11:50:52

标签: assembly x86 nasm

这是我的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'后,为什么会出现分段错误?

2 个答案:

答案 0 :(得分:4)

printret指令结束,这意味着您应该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)。