如何在x64汇编中在栈上声明局部数组并实现遍历求和?
在x64汇编栈上实现局部数组遍历求和的问题解决
你遇到的核心问题是栈上数组的寻址计算错误,以及循环逻辑的疏漏,以下是具体分析和修正方案:
原代码问题分析
- 寻址错误:栈向下增长,局部数组元素都在
%rbp的负偏移位置(如arr[0]是-8(%rbp),arr[4]是-40(%rbp)),但你用的(%rbp, %rcx, 8)计算的是%rbp + %rcx*8,指向的是%rbp上方的栈空间,完全不是数组元素。 - 循环逻辑漏洞:初始
%rcx=5,判断cmp $1, %rcx就跳转结束,只会执行4次循环,漏掉一个数组元素。
修正方案
方案1:用寄存器保存数组起始地址(推荐)
将数组的最低地址(最靠近栈顶的arr[4],即-40(%rbp))加载到寄存器,通过正索引配合scaled index遍历:
... subq $128, %rsp movq $100, -8(%rbp) # arr[0] = 100 movq $79, -16(%rbp) # arr[1] = 79 movq $85, -24(%rbp) # arr[2] = 85 movq $62, -32(%rbp) # arr[3] = 62 movq $91, -40(%rbp) # arr[4] = 91 movq $0, -48(%rbp) # sum = 0 lea -40(%rbp), %rbx # 把数组最低地址存入%rbx movq $0, %rcx # 遍历索引从0到4 loop: cmp $5, %rcx # 遍历完5个元素就结束 jge done movq (%rbx, %rcx, 8), %rax # 取%rbx + 8*%rcx地址的元素 addq %rax, -48(%rbp) # 累加到sum addq $1, %rcx # 索引自增 jmp loop done: ...
方案2:通过调整寄存器地址遍历
无需scaled index,直接移动寄存器地址来逐个访问数组元素:
... subq $128, %rsp movq $100, -8(%rbp) # arr[0] = 100 movq $79, -16(%rbp) # arr[1] = 79 movq $85, -24(%rbp) # arr[2] = 85 movq $62, -32(%rbp) # arr[3] = 62 movq $91, -40(%rbp) # arr[4] = 91 movq $0, -48(%rbp) # sum = 0 lea -8(%rbp), %rbx # 把arr[0]的地址存入%rbx movq $5, %rcx # 设置循环次数为5 loop: movq (%rbx), %rax # 取出当前元素 addq %rax, -48(%rbp) # 累加到sum subq $8, %rbx # 地址减8,移动到下一个元素(栈向下增长) subq $1, %rcx # 循环次数减1 jnz loop # 次数不为0则继续循环 done: ...
补充说明
x64汇编的scaled index模式不支持负scale因子,所以无法直接通过(%rbp, %rcx, -8)来寻址负偏移的数组元素,用寄存器保存起始地址或直接调整地址是更可靠的解决方式。
内容的提问来源于stack exchange,提问作者TheSinisterStone
相关产品推荐
相关产品推荐

