试图了解我做错了什么 - 链表 Y86 的迭代求和

Trying to understand what I'm doing wrong - Iterative sum of linked list Y86

我正在为一个 class 实验室做这件事,但我没有弄错。如果我用 l 而不是 q 作为后缀(例如 - andl 而不是 andq,rrmovl 而不是 rrmovq)而不是 q,程序就可以工作。如果有人指出我做错了什么,我将不胜感激。

   .pos 0
    init:   irmovq  Stack, %rsp     # Set up stack pointer
    rrmovq  %rsp,%rbp       # Set up base pointer
    irmovq  ele1,%rax
    pushq   %rax
    call    sum_list        # Execute main program
    halt                    # Terminate program


   # Sample linked list
    .align 8
    ele1:   .quad 0x00a
    .quad ele2
    ele2:   .quad 0x0b0
    .quad ele3
    ele3:   .quad 0xc00
    .quad 0

  # int sum_list(list_ptr ls)
    sum_list:   pushq   %rbp
        rrmovq  %rsp,%rbp
        xorq    %rax,%rax       # val = 0
        mrmovq  8(%rbp),%rdx    # edx = ls
        andq    %rdx,%rdx       # Set condition codes
        je      End
    Loop:       mrmovq  (%rdx),%rcx     # ecx = ls->val
        addq    %rcx,%rax       # val += ls->val
        mrmovq  4(%rdx),%rdx    # ls = ls->next ------ tried +8 insetead of 4 also
        andq    %rdx,%rdx       # Set condition codes
        jne     Loop
    End:        rrmovq  %rbp,%rsp
        popq    %rbp
        nop                     # makes sure stop in 31 steps
        ret

 # The stack starts here and grows to lower addresses
    .pos 0x100

堆栈:

我认为您获取的函数参数不正确:mrmovq 8(%rbp),%rdx 将函数的 return 地址放入 %rdx.

这恰好是 ele1 之前的几个字节,这解释了创建 "shifted" 值的偏移负载,而不会导致崩溃。不过,我不知道你怎么不在那之后立即崩溃。


您的指针 arg 由调用者使用 push %rax 放置在堆栈上。之后,call 推送一个 return 地址(8 字节)。

在您的函数中,push %rbp 在将其复制到 %rbp 之前将 %rsp 再减少 8 个字节。因此,调用者推送的指针 arg 位于 16(%rsp),这也是 16(%rbp).

mrmovq  16(%rbp),%rdx    # rdx = ls

调试时,请始终尝试检验您的假设。困难的部分有时是弄清楚 什么 你在假设什么,因为它通常是你甚至没有考虑过的可能问题困扰你的事情。 (例如,在这种情况下,获取函数参数。)


在寄存器中传递函数参数会更容易,就像 64 位 x86 代码一样。例如%rdi 中的第一个参数,%rsi 中的第二个参数是 x86-64 System V 调用约定所使用的。但是,如果您 "supposed to" 像 32 位 x86 调用约定一样在堆栈上传递参数,请记住每个 push 是 8 个字节宽。

OTOH,了解如何使用堆栈并跟踪调用/推送/弹出对其所做的操作很重要。