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

x86-64平台reduce高阶函数汇编实现段错误排查求助

x86-64平台reduce高阶函数汇编实现段错误排查

我需要在x86-64平台实现一个符合System V ABI调用约定的reduce高阶函数,功能对应如下C语言代码:

unsigned reduce( unsigned (*fnct_ptr) (unsigned param_one, unsigned param_two),
                    unsigned init,
                    size_t len,
                    const unsigned arr[]){
    for (int i = 0; i < len; i++) {
            init = fnct_ptr(init, arr[i]);
    }
    return init;
}

该函数接收双参数函数指针、初始值、数组长度和数组作为参数,我编写的汇编代码如下,但调用时出现段错误,怀疑是32位值与64位寄存器的地址大小不匹配导致,请求排查问题:

reduce:   

    XOR rbx, rbx    ; set counter to zero
    MOV rsp, rdi    ; fnctPntr -> rsp  
    MOV rax, rsi    ; init -> rax  
    
while:
    CMP rbx, rdx    ; if counter >= lengrh -> end 
    JGE  end
        
        MOV  rdi, rax          ; load parameters to rdi and rsi
        MOV  rsi, [rcx+rbx*8]  
        CALL rsp               ; call function with pointer 
        INC  rbx
        JMP  while
end:        
    RET    

错误排查与修复

你的代码存在三个核心问题,其中第一个是导致段错误的直接原因:

  • 错误1:非法修改栈指针rsp
    rsp是x86-64中维护栈结构的专用寄存器,你把函数指针从rdi移到rsp,直接破坏了栈的正常布局。调用CALL rsp时,CPU会把返回地址压入当前rsp指向的位置(也就是你存的函数指针地址),这会直接覆盖函数指针,同时后续栈操作完全混乱,必然触发段错误。
    修复:用非易失性通用寄存器存储函数指针,比如r12(System V ABI中r12-r15是调用者保存寄存器,需要先保存到栈),避免破坏rsp。

  • 错误2:数组元素访问宽度错误
    原数组元素是32位的unsigned类型,占4字节,但你用rbx*8按64位步长访问,会读取错误的内存数据,甚至导致越界访问。
    修复:将步长改为rbx*4,并且用mov esi, [rcx+rbx*4]加载32位元素,这样会自动零扩展到64位的rsi寄存器,符合System V ABI对32位整数参数的要求。

  • 错误3:违反寄存器调用约定
    rbx属于System V ABI中的非易失性寄存器,调用者需要保存其值后才能修改。你的代码直接修改rbx,会破坏调用者上下文的rbx值,导致后续潜在错误。
    修复:函数开头push rbx保存,结束前pop rbx恢复。

修复后的汇编代码

reduce:
    push rbx        ; 保存非易失性寄存器rbx
    push r12        ; 保存非易失性寄存器r12
    
    xor rbx, rbx    ; 初始化计数器为0
    mov r12, rdi    ; 将函数指针存入r12,避免破坏rsp
    mov eax, esi    ; 初始值存入eax(32位,自动零扩展到rax)

while:
    cmp rbx, rdx    ; 比较计数器与数组长度
    jge end         ; 计数器>=长度时跳转到结束
    
    mov edi, eax    ; 第一个参数:当前累计值(32位,零扩展到rdi)
    mov esi, [rcx + rbx*4] ; 第二个参数:数组当前元素(32位,零扩展到rsi)
    call r12        ; 调用传入的函数指针
    
    inc rbx         ; 计数器自增
    jmp while

end:
    pop r12         ; 恢复r12
    pop rbx         ; 恢复rbx
    ret

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:52:57