MacOS x86_64环境下nasm编写两数相加程序出现段错误求助
问题排查与修复
你的程序触发段错误是多个低级逻辑错误共同导致的,核心问题如下:
lea指令用法错误:lea EAX, [buffer]的作用是加载buffer的内存地址到EAX寄存器,而非读取buffer中存储的用户输入值。后续你直接把32位的地址值累加到仅预留了1字节可用空间的sum变量中,直接越界访问内存触发段错误。- 系统调用参数错误:
sys_read的第一个参数(存放在RDI寄存器)为文件描述符,标准输入对应的描述符是0,你错误填写为2(标准错误),属于不符合规范的写法,极易引发运行异常。 - 数据长度不匹配:你在操作单字节字符时使用了32位寄存器做运算,读写长度不匹配,会非法篡改相邻内存地址的数据。
修正后的可运行代码
section .text global _main default rel _main: ; 栈16字节对齐(macOS x86_64强制要求) sub rsp, 8 call _readData call _readData1 call _addData call _displayData add rsp, 8 mov RAX, 0x02000001 mov rdi, 0 syscall _addData: ; 读取输入的数字字符转成数值 mov al, [buffer] sub al, '0' mov bl, [buffer1] sub bl, '0' ; 相加后转回ASCII码 add al, bl add al, '0' mov [sum], al ret _readData: mov RAX, 0x02000003 mov RDI, 0 ; 标准输入文件描述符为0 mov RSI, buffer mov RDX, SIZE syscall ret _readData1: mov RAX, 0x02000003 mov RDI, 0 mov RSI, buffer1 mov RDX, SIZE syscall ret _displayData: mov RAX, 0x02000004 mov RDI, 1 mov RSI, sum mov RDX, 1 ; 只需要输出1字节的结果字符 syscall ret section .bss SIZE equ 4 buffer: resb SIZE buffer1: resb SIZE sum: resb SIZE
注:修正后的代码仅支持单个数字相加且和小于10的场景,如果你需要支持多位数、进位逻辑,需要额外扩展转换代码。
新手入门指南推荐
你可以按以下路径学习x86_64架构下的NASM汇编:
- 先通读NASM官方文档的入门章节,搞清楚NASM的基本语法、伪指令、不同平台的编译规则差异
- 再系统学习x86_64架构的基础知识点,包括寄存器用途、常用指令集、函数调用约定、系统调用规则
- 针对你使用的macOS平台,重点学习苹果官方文档中x86_64系统调用的ABI规范,明确栈对齐要求、寄存器破坏规则这些平台特有的约束
- 学习过程中从最小的demo开始写,先实现输出字符串、读取单个输入这种简单功能,跑通一个再扩展下一个功能,不要一开始就写复杂的多函数程序。
内容的提问来源于stack exchange,提问作者Tomasz Staszkiewicz
相关产品推荐
相关产品推荐

