linux 汇编时 segmentation fault,在汇编语言段错误(Segmentation Fault in Assembly Language)

我学习AT&T x86汇编语言。 我试图写汇编程序它接受一个整数n,然后返回结果(N / 2 + N / 3 + N / 4)。 这是我做了什么:

.text

.global _start

_start:

pushl $24

call profit

movl %eax, %ebx

movl $1, %eax

int $0x80

profit:

popl %ebx

popl %eax

mov $0, %esi

movl $4, %ebp

div %ebp

addl %eax, %esi

movl %ecx, %eax

movl $3, %ebp

div %ebp

addl %eax, %esi

movl %ecx, %eax

movl $2, %ebp

div %ebp

addl %eax, %esi

movl %esi, %eax

cmpl %ecx, %esi

jg end

pushl %ebx

ret

end:

mov %ecx, %eax

ret

问题是我得到段错误。 问题出在哪儿?

Answer 1:

我认为这里的代码失败:

_start:

pushl $24

call profit

movl %eax, %ebx

movl $1, %eax

int $0x80

profit:

popl %ebx

popl %eax

所以,你push $24 (4个字节),然后call profit ,这推动eip ,并跳转到profit 。 然后你弹出的价值eip到ebx和价值$24到eax 。

然后,在最后,如果jg end分支end: ,那么栈将不会持有有效的返回地址和ret将失败。 你可能需要pushl %ebx有太多。

cmpl %ecx, %esi

jg end

pushl %ebx

ret

end:

mov %ecx, %eax

; `pushl %ebx` is needed here!

ret

Answer 2:

你似乎并没有被正确地做函数调用。 你需要阅读和理解的x86 ABI( 32位 , 64位 ),特别是“调用约定”部分。

此外,这是不是你的眼前问题,但:不要写_start ,写main仿佛这是一个C程序。 当你开始做更复杂的东西,你会希望C库可用,这意味着你必须让它初始化。 与此相关的, 不要让自己的系统调用; 调用C库的包装。 那你隔离在内核接口的低层次的变化,保证了errno是可用的,等等。

Answer 3:

你用ecx而没有明确地初始化它(我不知道如果Linux将保证状态ecx过程开始时-看起来像它的0在实践中,如果没有规则)

当程序需要的jg end接近过程结束跳跃,返回地址是在栈上不再,所以ret将控制转移到一些垃圾地址。

Answer 4:

你的问题是,你弹出的返回地址从堆栈中的,当你转移到结束不还原它。 一个快速的解决办法是增加push %ebx那里。

你应该做的是修改你的过程,以便正确地使用调用约定。 在Linux中,调用函数预计清理从堆栈中的参数,所以你的程序应该让他们身在何处。

而不是这样做是为了获取参数,然后再恢复的返回地址

popl %ebx

popl %eax

你应该这样做,并留下寄信人地址和论据他们在哪里

movl 4(%esp), %eax

和摆脱将返回地址返回到堆栈中的代码。 然后,您应该添加

subl $4, %esp

在调用程序后,删除从堆栈的说法。 它如果您希望能够从其他语言调用你的组装程序正确地遵循这个惯例是很重要的。

Answer 5:

它看起来像你对我有一个pushl你打电话的利润,然后第一件事,利润确实是做两个popl等指令之前。 我希望这会弹出你压入堆栈的值以及返回代码,使您的RET是行不通的。

push和pop应该是相同的次数。

通话将返回地址压入堆栈。

文章来源: Segmentation Fault in Assembly Language

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值