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

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

修复说明

  1. 修正参数传递:使用rdi接收传入的字符串指针,符合X64调用约定
  2. 新增字符串复制:将只读常量字符串复制到栈上的可写缓冲区,避免修改只读内存
  3. 代码可读性优化:用字符常量'a'、'z'替代十六进制值,逻辑更直观
  4. 栈帧规范:保留标准栈帧结构,避免破坏调用者寄存器状态

内容的提问来源于stack exchange,提问作者Joao Pereira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:50:15