assembly 如何在x64程序集中声明堆栈上的局部数组?

a8jjtwal  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(134)

我试图在x64汇编程序的堆栈中声明一个“四字”数组。我知道如何在.data段中声明数组,但如果可能的话,我希望将数组设置为main的本地数组。我知道我可能也可以使用malloc和动态内存分配来实现此操作。但我首先想看看是否有可能在堆栈上执行此操作。我的问题是我在堆栈上声明了足够的内存来存储数组(为了更好地度量,还需要一些额外的空间)。我将初始值存储到数组元素中,但我不知道如何“迭代"索引。我想对数组中的所有值求和,只是为了练习。我尝试使用movq检索元素,从数组的起始索引开始偏移,但我不能在”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
     movq $5, %rcx # movq i = 5
 loop:
     cmp $1, %rcx
     jz done
     movq (%rbp, %rcx, 8), %rax # I believe this line may be wrong because the array starts at index -8(%rbp), right?
     addq %rax, -48(%rbp)
     subq $1, %rcx
     jmp loop
     ...
cuxqih21

cuxqih211#

在这个答案中,我展示了几种修改代码的方法,第一种是对原始代码进行最小的修改,使其正常工作;最后一个是我的写法。
第一个例子只改变了rcx的起始值和结束值,它以不寻常的自上而下的顺序将数组留在堆栈中,并从数组的末尾迭代到数组的开头。

...
    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
    movq $-5, %rcx
loop:
    cmp $0, %rcx
    jz done
    movq (%rbp, %rcx, 8), %rax
    addq %rax, -48(%rbp)
    addq $1, %rcx
    jmp loop

下一个示例以通常的方式将数组放入内存中,索引0位于最低地址,并从索引0迭代到4。请注意load指令上的偏移量,该偏移量导致索引0访问rbp-40。

...
    subq $128, %rsp
    movq $100, -40(%rbp) # arr[0] = 100
    movq $79, -32(%rbp) # arr[1] = 79
    movq $85, -24(%rbp) # arr[2] = 85
    movq $62, -16(%rbp) # arr[3] = 62
    movq $91, -8(%rbp) # arr[4] = 91
    movq $0, -48(%rbp) # sum = 0
    movq $0, %rcx # i = 0
loop:
    cmp $5, %rcx
    jz done
    movq -40(%rbp, %rcx, 8), %rax
    addq %rax, -48(%rbp)
    addq $1, %rcx
    jmp loop

最后一个例子改变了一些其他的东西,以匹配我的写作方式:

...
    subq $128, %rsp
    movq $100, -40(%rbp) # arr[0] = 100
    movq $79, -32(%rbp)  # arr[1] = 79
    movq $85, -24(%rbp)  # arr[2] = 85
    movq $62, -16(%rbp)  # arr[3] = 62
    movq $91, -8(%rbp)   # arr[4] = 91
    xor %eax, %eax       # sum = 0
    xor %ecx, %ecx       # i = 0
loop:
    addq -40(%rbp, %rcx, 8), %rax
    add $1, %ecx
    cmp $5, %ecx
    jb loop

这个版本将总和保存在寄存器中而不是内存中。它利用了这样一个事实,即写入64位寄存器的下半部分会清除寄存器的上半部分。它使用通常的技术将0加载到寄存器中。它将循环条件放在循环的底部而不是顶部。

相关问题