x86组装,出现分段错误 [英] x86 Assembly, getting segmentation fault

查看:55
本文介绍了x86组装,出现分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

section .data
msg: db "hello!", 10, 0 ;my message

section .text
extern printf ;C printf function
global main
main:
    push ebp
    mov ebp, esp
    call print_string
    mov esp, ebp
    pop ebp
    ret ;end of program

print_string:
    pusha
    push msg
    call printf ;should print "Hello"
    popa
    ret ;return back to main

运行此代码时,我得到:
你好!
分段错误(核心已转储)

When I run this code I get:
hello!
Segmentation fault (core dumped)

代码有什么问题?

推荐答案

print_string子例程正在修改堆栈指针而不恢复它. 子例程main具有以下布局:

The print_string subroutine is modifying the stack pointer without restoring it. The subroutine main has the following layout:

push ebp    ;save the stack frame of the caller
mov ebp, esp    ;save the stack pointer
<code for subroutine>
mov esp, ebp    ;restore the stack pointer
pop ebp    ;restore the caller's stack frame
ret ;return to address pushed onto the stack by call

类似地,print_string子例程应该具有相同的布局,保存堆栈指针,然后在ret之前恢复它.任何使用堆栈的子例程都应保存并恢复堆栈指针.

Similarly, the print_string subroutine should have that same layout, saving the stack pointer and then restoring it before reting. Any subroutines that use the stack should save and restore the stack pointer.

push ebp
mov ebp, esp
pusha
push msg
call printf ;should print "Hello"
add esp, 4
popa
mov esp, ebp
pop ebp
ret

在不保存堆栈指针并对其进行恢复的情况下,被调用的子例程会修改堆栈指针,其中call指令在其中保存了返回地址.因此,当遇到ret时,执行将跳转到错误的返回地址,从而导致段错误.在汇编中的调用约定和函数上了解更多信息.

Without saving the stack pointer and restoring it, the called subroutine modifies the stackpointer, where the call instruction saved the return address. Consequently, when ret is encountered, execution jumps to the wrong return address, therefore segfaulting. Read more on calling conventions and functions in assembly.

这篇关于x86组装,出现分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆