X64汇编字符串转大写函数触发SIGBUS错误求助
X64汇编字符串转大写函数的SIGBUS错误排查与修复
核心错误点
- 调用约定误用:X64 System V ABI(Linux/macOS主流调用约定)中,第一个函数参数通过
rdi寄存器传递,而非rax。你的代码中mov rbp, [rax]完全错误:rax并非参数传递寄存器,且字符串参数本身就是指针,不需要解引用操作。 - 修改只读内存:C代码传入的
"abcdef\n"是字符串常量,被编译器放置在只读数据段,直接执行sub byte [rbp+rcx], 20h修改该内存会触发内存访问异常。
修复后的代码
asm_func3: ; 创建栈帧并分配可写缓冲区 push rbp mov rbp, rsp sub rsp, 256 ; 分配256字节栈空间存储字符串副本 mov rsi, rdi ; rsi = 源字符串指针(rdi为传入的第一个参数) mov rdi, rbp ; rdi = 目标缓冲区地址(栈上) xor rcx, rcx ; 计数器清零 _copy_str: ; 将只读字符串复制到栈上可写缓冲区 mov al, byte [rsi+rcx] mov byte [rdi+rcx], al cmp al, 0 ; 判断是否到达字符串结束符 je _convert_start inc rcx jmp _copy_str _convert_start: xor rcx, rcx ; 重置计数器 _toupper: mov al, byte [rdi+rcx] cmp al, 0 je _toupper_end ; 判断是否为小写字母 cmp al, 'a' jl _toupper_next cmp al, 'z' jg _toupper_next ; 转换为大写 sub byte [rdi+rcx], 32 _toupper_next: inc rcx jmp _toupper _toupper_end: mov rax, rdi ; 返回转换后的字符串指针 leave ; 恢复栈帧 ret
修复说明
- 修正参数传递:使用
rdi接收传入的字符串指针,符合X64调用约定 - 新增字符串复制:将只读常量字符串复制到栈上的可写缓冲区,避免修改只读内存
- 代码可读性优化:用字符常量
'a'、'z'替代十六进制值,逻辑更直观 - 栈帧规范:保留标准栈帧结构,避免破坏调用者寄存器状态
内容的提问来源于stack exchange,提问作者Joao Pereira
相关产品推荐
相关产品推荐

