x86-64汇编数组访问异常:array[0]始终返回0排查
问题分析:array[0]始终返回0的原因及修复方案
核心错误
你在定义完数组后执行的push $0操作直接覆盖了数组的第一个元素(索引0对应的85),导致后续读取时只能得到0。
栈布局详细分析
- 进入
usr_main后,push %rbp+movq %rsp, %rbp让rbp指向当前栈顶(保存的旧rbp值),此时rsp和rbp地址完全相同。 - 你将数组元素依次存在
-8(%rbp)到-40(%rbp)的位置——也就是rbp下方8到40字节的栈区域,其中-8(%rbp)存储的是数组第一个元素85。 - 执行
push $0时,CPU会先把rsp减8(变成rbp-8),然后把0写入这个地址。而这个地址正好是你刚存入85的-8(%rbp),直接把数组第一个元素覆盖成了0。
修复方案
方案一:调整栈操作避免覆盖数组
先为offset预留独立的栈空间,再定义数组,避免push操作破坏数组元素:
usr_main: .cfi_startproc push %rbp movq %rsp, %rbp # 先为offset分配独立栈空间,不占用数组区域 subq $8, %rsp movq $0, (%rsp) # define array movq $85, -8(%rbp) movq $15, -16(%rbp) movq $76, -24(%rbp) movq $58, -32(%rbp) movq $17, -40(%rbp) # Evaluate computed array expr (index expr) # IndexExpr Step 1: Evaluate offset of array movq (%rsp), %rdx # IndexExpr Step 2: Evaluate computed expr (the index) movq $0, %rbx # index of 0 # IndexExpr Step 3: Calculate rbp offset add %rdx, %rbx neg %rbx # IndexExpr Step 4: Read array element movq -8(%rbp, %rbx, 8), %rax movq %rbp, %rsp pop %rbp ret .cfi_endproc .size usr_main, .-usr_main
方案二:直接用寄存器存储offset(更简洁)
既然当前offset值为0,完全可以省去push操作,直接把offset值加载到寄存器:
usr_main: .cfi_startproc push %rbp movq %rsp, %rbp # define array movq $85, -8(%rbp) movq $15, -16(%rbp) movq $76, -24(%rbp) movq $58, -32(%rbp) movq $17, -40(%rbp) # Evaluate computed array expr (index expr) # IndexExpr Step 1: Evaluate offset of array movq $0, %rdx # 直接设置offset为0,无需栈存储 # IndexExpr Step 2: Evaluate computed expr (the index) movq $0, %rbx # index of 0 # IndexExpr Step 3: Calculate rbp offset add %rdx, %rbx neg %rbx # IndexExpr Step 4: Read array element movq -8(%rbp, %rbx, 8), %rax movq %rbp, %rsp pop %rbp ret .cfi_endproc .size usr_main, .-usr_main
修复后,-8(%rbp)的85不会被覆盖,读取array[0]时就能得到正确值,其他索引的逻辑不受影响。
内容的提问来源于stack exchange,提问作者MrEthanVlogsandGames
相关产品推荐
相关产品推荐

