反向数组 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 语法的主要内容,如果未能解决你的问题,请参考以下文章

x86 AT&T 语法程序集的注释语法

x86汇编程序基础(AT&T语法)

AT&T 语法中的 3 或 4 参数 x86 程序集[重复]

x86 程序集:“subl”命令如何在 AT&T 语法中工作

x86-64 汇编中的数组元素比较(AT&T 语法)

x86 AT&T 寻址模式中基址寄存器的省略