反向数组 X86 AT&T 语法
Posted
技术标签:
【中文标题】反向数组 X86 AT&T 语法【英文标题】:Reverse Array X86 AT&T Syntax 【发布时间】:2018-04-19 01:48:52 【问题描述】:我正在用 Assembly 编写一个程序,它在开头声明了 2 个数组和 3 个函数,它们是:
printQArray(int size, long *array1)
invertArray(int size, long *array1)
multQuad(int size, long *array1, long *array2)
现在程序获取这些数组并打印每个对应位置的 2 个数组的乘积并打印它们。 然后它打印 Array1。 然后它打印 Array1 Reversed。 然后它应该取反转数组并再次调用乘法函数并打印第一个数组反转的位置和第二个永远不会改变的数组的位置的乘积。(源代码中的数组值)
我在反转数组并尝试将反转的第一个数组和第二个数组相乘后遇到问题。
以下是我程序的输出
Products
200
-925
1386
-2928
9375
64350
Elements in QArray1
10
25
33
48
125
550
Elements in QArray1
550
125
48
33
25
10
Products
0
-1036
-31584
44896
0
0
所以最后这个输出显然不是array1 reversed 和array2 的乘积
正如您在下面的代码中看到的(PS 我已经尝试用 movq 代替 leaq)我的反转数组在 %rax 中返回,我将它放入 %rcx 这一切都很好,因为我成功打印出下面的反转数组
#PRINT Inverted ARRAY1 void printArray(int size, long *array1);
movq $sizeQArrays, %rax
movq (%rax), %rdi #sizeQArrays to %rdi (parameter 1)
leaq (%rcx), %rsi #put reversed array into rsi
call printQArray
movq $0, %rax
但是,一旦我再次调用 multQuads,我会得到奇怪的结果,我确信我的反转数组没有正确地移入寄存器。原始数组是一个常量,因此很简单,但我认为我将所有值推入堆栈并以相反的顺序弹出它们以某种方式改变了结构。或者,也许我有一个错字。源码如下:
.section .rodata
.LC1: .string "Products\n"
.LC3: .string "Elements in QArray1\n"
.LC4: .string "%i\n"
.LC5: .string "\n"
.data
sizeQArrays:
.quad 6
QArray1:
.quad 10
.quad 25
.quad 33
.quad 48
.quad 125
.quad 550
QArray2:
.quad 20
.quad -37
.quad 42
.quad -61
.quad 75
.quad 117
.globl main
.type main, @function
.globl printQArray
.type printQArray, @function
.globl multQuads
.type multQuads, @function
.globl invertArray
.type invertArray, @function
.text
main:
pushq %rbp #stack housekeeping
movq %rsp, %rbp
#order of calls: quad print invert print quad
#MULTQUADS void multQuads(int size, long *array1, long *array2)
movq $sizeQArrays, %rax
movq (%rax), %rdi #1st param
movq $QArray1, %rsi #2nd Param
movq $QArray2, %rdx #3rd Param
call multQuads
movq $0, %rax
#PRINT ARRAY1 void printArray(int size, long *array1);
movq $sizeQArrays, %rax
movq (%rax), %rdi #sizeQArrays to %rdi (parameter 1)
movq $QArray1, %rsi #address of QArray1 to %rsi (parameter 2)
#purposely not pushing anything because I have not put anything in registers
#except parameters and I will be putting new values there after return
call printQArray
movq $0, %rax
#InvertArray void invertArray(long size, long *array1)
movq $sizeQArrays, %rax
movq (%rax), %rdi #1st param
movq $QArray1, %rsi #2nd Param
call invertArray
leaq (%rax), %rcx #put inverted array into %rcx
movq $0, %rax #set %rax back to 0
#PRINT Inverted ARRAY1 void printArray(int size, long *array1);
movq $sizeQArrays, %rax
movq (%rax), %rdi #sizeQArrays to %rdi (parameter 1)
movq %rcx, %rsi #put reversed array into rsi
call printQArray
movq $0, %rax
#MULTQUADS W/ REVERSED ARRAY void multQuads(int size, long *array1, long *array2);
movq $sizeQArrays, %rax
movq (%rax), %rdi #1st param
movq %rcx, %rsi #inversed array as 2nd param
movq $QArray2, %rdx #3rd Param
call multQuads
movq $0, %rax
#END of main
leave
ret
.size main, .-main
#printQArray prints an array of 8 byte values
# the size of the array is passed in %rdi,
# a pointer to the beginning of the array is passed in %rsi
printQArray:
pushq %rbp
movq %rsp, %rbp
pushq %r12
pushq %r13
pushq %rbx
movq %rdi, %r12 #copy size to %r12
movq %rsi, %r13 #copy array pointer to %r13
# print array title
movq $.LC3, %rdi
movq $0, %rax
# purposely not pushing any caller save registers.
callq printf
movq $0, %rbx #array index
printQArrayLoop:
movq (%r13, %rbx, 8), %rsi #element of array in 2nd parameter register
movq $.LC4, %rdi #format literal in 1st parameter register
movq $0, %rax
#purposely not pushing any caller save registers
callq printf
incq %rbx #increment index
decq %r12 #decrement count
jle printQArrayExit
jmp printQArrayLoop
printQArrayExit:
# print final \n
movq $.LC5, %rdi #parameter 1
movq $0, %rax
call printf
popq %rbx
popq %r13
popq %r12
leave
ret
.size printQArray, .-printQArray
multQuads:
pushq %rbp
movq %rsp, %rbp
pushq %r12
pushq %r13
pushq %r14
pushq %rbx
movq %rdi, %r12 #copy size to %r12
movq %rsi, %r13 #copy array1 pointer to %r13
movq %rdx, %r14 #copy array2 pointer to %r14
# print "Products"
movq $.LC1, %rdi
movq $0, %rax
call printf
movq $0, %rbx #array index
multQuadLoop:
movq (%r13, %rbx, 8), %rsi #element of array in 2nd parameter register
movq (%r14, %rbx, 8), %rdx #element of array in 3rd parameter register
movq $.LC4, %rdi #format literal in 1st parameter register
imulq %rdx, %rsi #insert product into second parameter
movq $0, %rax
callq printf
incq %rbx #increment index
decq %r12 #decrement count
jle multQuadExit
jmp multQuadLoop
multQuadExit:
# print final \n
movq $.LC5, %rdi #parameter 1
movq $0, %rax
call printf
popq %rbx
popq %r13
popq %r12
popq %r14
leave
ret
.size multQuad, .-multQuad
invertArray:
pushq %rbp
movq %rsp, %rbp
pushq %r12 #size
pushq %r13 #array pointer
pushq %rbx #array index
pushq %r9 #holder
pushq %r10 #holder
push %r14
movq %rdi, %r12 #copy size to %r12
movq %rdi, %r9
movq %rsi, %r13 #copy array pointer to %r13
movq $0, %rbx #array index
movq $0, %r10
invertArrayLoop:
pushq (%r13, %rbx, 8) #push elements of array onto stack
incq %rbx #increment index
decq %r12 #decrement count
jle reverseArray
jmp invertArrayLoop
reverseArray:
popq %r14
movq %r14, (%r13, %r10, 8)
incq %r10
decq %r9
subq %r12, %r9
jle invertArrayExit
jmp reverseArray
invertArrayExit:
movq %r13, %rax
popq %r14
popq %r10
popq %r9
popq %rbx
popq %r13
popq %r12
leave
ret
.size invertArray, .-invertArray
如果 multQuad 函数第一次工作并且我可以正确打印出反转的数组,那么我想问题必须在我调用 multQuad 并设置寄存器之前就出现了
【问题讨论】:
【参考方案1】:我在 printQArray 中丢失了数组
只有一行!!
【讨论】:
函数调用破坏一些寄存器是正常的;如果您希望值在函数调用中继续存在,请将值保留在调用保留寄存器中(根据调用约定)。 agner.org/optimize/calling_conventions.pdf 有一些很好的信息。有关 ABI 链接,另请参阅 ***.com/tags/x86/info。以上是关于反向数组 X86 AT&T 语法的主要内容,如果未能解决你的问题,请参考以下文章
AT&T 语法中的 3 或 4 参数 x86 程序集[重复]