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

x86汇编中栈分配的两个数组为何出现互相覆盖问题

错误定位与修复方案

核心错误点

    1. names_ptr赋值错误
      你在分配姓名数组的代码中,执行完栈对齐操作后,错误将值为0的rax赋值给names_ptr,而非当前栈指针rsp:
      原错误代码:
and rsp, -16
mov [names_ptr], rax ; rax此时为0,names_ptr被错误设为0地址

正确写法应为mov [names_ptr], rsp。

    1. 数组索引逻辑错误
      names_ptr和grades_ptr是存储数组基地址的指针变量,你直接对变量本身的地址做偏移计算,相当于在指针变量所在的内存区域读写数据,而非读写指针指向的数组内存:
      原错误索引代码:
lea rsi, [names_ptr+rbx*8] ; 取names_ptr变量自身地址加偏移,不是数组地址偏移

正确索引逻辑需要先取出指针存储的基地址,再计算偏移:

mov rsi, [names_ptr]
lea rsi, [rsi + rbx*8]

成绩数组的索引逻辑存在同样的错误,需要同步修正。

    1. 错误修改rbp寄存器
      main函数开头已经将原始栈顶存入rbp用于后续栈恢复,但你在分配成绩数组前又执行了mov rbp, rsp覆盖了原始rbp值,会导致函数退出时栈恢复错误,直接删除这行多余的赋值即可。
    1. 姓名数组元素大小不匹配
      你使用%10s格式读取字符串,10个字符加结束符共需要11字节存储空间,但你每个数组元素仅分配8字节,会导致缓冲区溢出。可以选择两种修复方式:
    • 将数组元素大小调整为16字节,计算数组总大小的时候用shl rdi, 4代替shl rdi, 3
    • 将字符串读取格式改为%7s,保证输入的字符串加结束符不超过8字节
    1. 指针变量分配冗余
      bss段中names_ptr和grades_ptr各分配了2个8字节空间,实际只需要存储1个指针,改为resq 1即可。

修正后的栈分配核心代码示例

mov rdi, [num_students]
shl rdi, 3 ; 若调整姓名元素大小为16则改为shl rdi,4
sub rsp, rdi
and rsp, -16
mov [names_ptr], rsp ; 修正为给names_ptr赋rsp值

mov rdi, [num_students]
shl rdi, 3
sub rsp, rdi
and rsp, -16
mov [grades_ptr], rsp 

修正后的数组读取示例

_get_student:
    call _prompt_name
    xor rax, rax
    mov rdi, stud_name_format
    mov rsi, [names_ptr] ; 先取数组基地址
    lea rsi, [rsi + rbx*8] ; 计算元素偏移,元素大小调整的话对应修改乘数
    call scanf

    call _prompt_grade
    xor rax, rax
    mov rdi, int_format
    mov rsi, [grades_ptr] ; 先取成绩数组基地址
    lea rsi, [rsi + rbx*8]
    call scanf

    inc rbx
    cmp rbx, [num_students]
    jl _get_student

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 23:06:03