0

我正在为课堂实验室做这个,但我没有找到我要去的地方。如果我用 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

堆:

4

1 回答 1

1

我认为您错误地获取了函数参数: mrmovq 8(%rbp),%rdx将函数的返回地址放入%rdx.

这恰好是之前的几个字节ele1,这解释了创建“移位”值的偏移负载,而您看到的不是崩溃。不过,IDK 你如何不会在那之后立即崩溃。


调用者将指针 arg 放在堆栈上push %rax。之后,call推送一个返回地址(8 个字节)。

在您的函数内部,push %rbp%rsp将其复制到%rbp. 因此,调用者推送的指针 arg 位于16(%rsp),这也是16(%rbp)

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

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


在寄存器中传递函数参数会更容易,就像 64 位 x86 代码一样。例如 first arg in %rdi, second in%rsi是 x86-64 System V 调用约定使用的。但是,如果您“应该”像 32 位 x86 调用约定一样在堆栈上传递参数,请记住每个参数push都是 8 个字节宽。

OTOH,重要的是要知道如何使用堆栈,并跟踪对它执行的调用/推送/弹出操作。

于 2017-11-24T23:30:27.760 回答