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

x86汇编实现1D Stencil时栈缓冲区溢出问题求助

问题原因分析与修复方案

错误根源

你遇到的栈缓冲区溢出错误,由两个核心问题导致:

1. 调用约定参数处理错误

Windows x64平台采用fastcall调用约定,函数前三个参数通过寄存器传递:RCX(第一个参数X)、RDX(第二个参数Y)、R8(第三个参数n)。但你的汇编代码错误地从栈帧(rbp+16、rbp+24)读取参数,导致X和Y的指针指向非法内存,后续数组访问直接越界。

2. 循环范围错误导致数组越界

你的Stencil计算式要求i的有效范围是 3 ≤ i ≤ n-4(因为i-3 ≥ 0且i+3 < n),但原汇编循环从ecx=0开始,一直执行到ecx == n,会触发两种越界:

  • 当ecx < 3时,访问X[i-3](比如i=0时访问X[-3]),属于数组前越界;
  • 当ecx > n-4时(比如i=7时,i+3=10超出X[0..9]的索引范围),属于数组后越界;
    这种越界直接破坏了编译器添加的栈保护cookie,触发溢出检测报错。

修复后的汇编代码

section .text
    global stencil_function

stencil_function:
    push rbp
    mov rbp, rsp

    ; 保存非易失性寄存器(符合Windows x64调用约定规范)
    push rbx
    push rsi
    push rdi

    ; 从调用约定寄存器获取参数
    mov rdi, rcx    ; X = RCX
    mov rsi, rdx    ; Y = RDX
    mov rbx, r8     ; n = R8

    ; 设置有效循环范围:i从3开始,到n-4结束
    mov ecx, 3
    mov edx, ebx
    sub edx, 4      ; edx = n-4

stencil_loop:
    cmp ecx, edx
    jg end_loop     ; i > n-4时退出循环

    ; 执行Stencil计算
    mov eax, dword [rdi + rcx*4 - 12] ; X[i-3]
    add eax, dword [rdi + rcx*4 - 8]  ; +X[i-2]
    add eax, dword [rdi + rcx*4 - 4]  ; +X[i-1]
    add eax, dword [rdi + rcx*4]      ; +X[i]
    add eax, dword [rdi + rcx*4 + 4]  ; +X[i+1]
    add eax, dword [rdi + rcx*4 + 8]  ; +X[i+2]
    add eax, dword [rdi + rcx*4 + 12] ; +X[i+3]

    mov dword [rsi + rcx*4], eax      ; 结果存入Y[i]

    inc ecx
    jmp stencil_loop

end_loop:
    ; 恢复寄存器
    pop rdi
    pop rsi
    pop rbx

    pop rbp
    ret

修复说明

  1. 修正参数传递:直接使用Windows x64约定的寄存器获取X、Y、n,避免栈帧读取错误;
  2. 限制循环范围:只处理有效的i值,彻底杜绝数组越界;
  3. 符合调用约定:保存并恢复非易失性寄存器(RBX、RSI、RDI),避免破坏调用者的寄存器状态。

运行修复后的代码,将正常输出Y = 28 35 42,对应Y[3]=1+2+3+4+5+6+7=28、Y[4]=2+3+4+5+6+7+8=35、Y[5]=3+4+5+6+7+8+9=42,与预期一致。

内容的提问来源于stack exchange,提问作者Stephanie Joy Relles

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 23:27:45