4

我正在 x86 汇编中进行快速排序,我需要交换数组 A[pivot] 和 A[j] 的两个元素,但我什至无法为数组索引分配值,更不用说交换元素了。

数组是这样分配的:

A:      .long   2,1,8,6,12

我最初的交换计划根本不起作用,所以我将其简化为了解我的问题所在。我尝试了多种方法来获得正确的结果,但都导致错误的值或分段错误

    movl    A(,%ebx,4), %eax            #eax = A[pivot]
    movl    A(,%edi,4), %edx            #edx = A[j]


                                        #ebx = pivot = 0
                                        #edi = j = 1

    pushl   %eax
    pushl   $test7                      #"A[pivot] = %d"
    call    printf
    addl    $8, %esp                    # A[0] = 2 

    pushl   %edx
    pushl   $test8                      #"A[j] = %d"
    call    printf
    addl    $8, %esp                   #A[1] = 1

此代码段返回:

A[pivot]         = 2 
A[j]             = -143535296 

A[pivot] = A[0] = 2,所以这是正确的,但是 A[j] = A[1] = 1

当 %ebx 和 %edi 是两个数组索引以查看它们的内容或更改它们的值时,这是引用数组元素的正确方法吗?

无法弄清楚我做错了什么,任何帮助将不胜感激。

编辑:另外,如果我使用 A(,[index],4) 作为 printf 参数,它会显示正确的值。

编辑1:我意识到为什么我的 printf 语句不正确,我更改了代码,它返回了似乎是正确的内存地址。addr[A] = 134513652 和 addr[A+1] = 134513656。我原来更改数组值的问题仍然存在,但执行此操作时仍然出现分段错误:

    leal    A(,%ebx,4), %ecx        # ecx = addr[A[0]]          
    movl    A(,%edi,4), %edx        # edx = A[1]
    movl    %edx, (%ecx)            # (ecx) = edx
4

1 回答 1

1

您应该阅读有关调用约定的信息,尤其是。被调用者和调用者保存寄存器。在许多 ia32 调用约定中,EAX、ECX 和 EDX 都是调用者保存寄存器。这意味着一个调用——在你的情况下是第一个 printf 调用——可能会改变它们的值。它被称为调用者保存,因为您作为调用者负责保存值,例如使用推送/弹出指令。您的示例也可以通过使用被调用者保存的寄存器之一来修复。

于 2013-03-18T17:24:23.187 回答