You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在x86汇编中实现简单print函数时遇段错误求助

错误分析

  1. 栈帧参数偏移计算错误
    进入print函数后,32位环境下的栈帧结构(每个栈项4字节):

    • [ebp]:保存的旧EBP值
    • [ebp+4]:函数返回地址
    • [ebp+8]:第一个参数msg(字符串地址)
    • [ebp+12]:第二个参数len(字符串长度)
      你代码中用[bp+4]和[bp+6]读取参数,拿到的是返回地址的部分无效数据,这是引发段错误的核心原因。
  2. 参数压栈顺序与方式错误

    • C调用约定(cdecl)下,函数参数需从右往左压栈,print(msg, len)应该先压入长度13,再压入字符串地址msg,你写反了顺序。
    • push [msg]是取msg地址指向的第一个字节('H'的ASCII码),而非msg本身的地址,应该直接push msg(msg是字符串的起始地址标签)。
  3. 系统调用参数寄存器对应错误
    Linux 32位write系统调用(eax=4)的参数对应关系:

    • ebx:文件描述符(1代表标准输出)
    • ecx:字符串缓冲区的起始地址
    • edx:字符串的长度
      你代码中把长度放到ecx、地址放到edx,完全搞反,导致write尝试读取错误的内存区域。
  4. ret指令清理栈的字节数错误
    调用print时压入了两个4字节参数(共8字节),ret 4仅清理4字节,会导致栈指针不平衡,后续执行exit系统调用时栈状态异常。


修正后的代码

.global _start
.intel_syntax noprefix
.section .text    

# void print(char *msg, int len) 
print:
    push ebp
    mov ebp, esp

    mov ecx, [ebp+8]    # 第一个参数:msg地址
    mov edx, [ebp+12]   # 第二个参数:长度len

    mov eax, 4          # write系统调用号
    mov ebx, 1          # 标准输出文件描述符
    int 0x80

    pop ebp
    ret 8               # 清理两个4字节参数,共8字节

_start:
    push 13             # 先压入第二个参数:长度
    push msg            # 再压入第一个参数:msg地址
    call print

    mov eax, 1          # exit系统调用号
    mov ebx, 0          # 退出码0
    int 0x80

.section .data
msg:
    .ascii "Hello, world!\n"

编译运行验证

仍使用你原来的命令:

as test.asm --32 -o test.o 
gcc -m32 test.o -nostdlib

运行编译后的程序即可正常输出Hello, world!。

内容的提问来源于stack exchange,提问作者Leon Gurin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 20:11:09