理解堆栈和基址指针Y86 - 链接列表总和

时间:2017-11-26 08:05:10

标签: assembly y86

注意:这是一个班级。我只是想了解rsp和rbp是如何工作的,这样我才能理解我的代码中哪些部分搞砸了。对不起,我是新来的。谢谢你的帮助。

所以我编写Y86代码来查找链表的节点总和

        .pos 0
    init:   irmovq  Stack, %rsp     # Set up stack pointer
    rrmovq  %rsp,%rbp       # Set up base pointer
    irmovq  ele1,%rdi
    irmovq  $18, %r8        #Note 1 : unsure of what this should be
    call    rsum_list        # Execute main program
    halt                    # Terminate program


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

        # int sum_list(list_ptr ls)
  rsum_list:  pushq   %rbp
        rrmovq  %rsp,%rbp
        xorq    %rax,%rax       # val = 0
        subq %r8, %rsp              #subtract constant from rsp , not sure why we need to do this -> saw this in x86 code
        rmmovq %rdi, -18(%rbp)      #move ls to -18(%rbp)
        andq %rdi, %rdi             #check if 0   
        je End
        mrmovq -18(%rbp), %rax
        mrmovq (%rax), %rax            #rax gets ls->val
        rmmovq %rax, -10(%rbp)         #the val obtained is stored in -10(%rbp)
        mrmovq -18(%rbp), %rax         #rax becomes ls again
        mrmovq 8(%rax), %rax          # rax gets ls-> next
        rmmovq %rax, %rdi             #this is copied to rdi for next recursive call
        call rsum_list
        rmmovq %rax, -8(%rbp)          #rax will contain ans from recursive call
        mrmovq -10(%rbp), %rdx       #retrieve ans. of current node from -10(%rbbp) , where we stored it before recursion
        mrmovq -8(%rbp), %rax      
        addq %rdx, %rax           #adding

  End :
       rrmovq %rbp, %rsp
       popq %rbp
       nop                     # makes sure stop in 31 steps
       ret

我怀疑我在堆栈中存储由于递归引起的混乱的错误时犯了一个错误。对不起,我真的不理解这个并且想要。任何帮助表示赞赏。谢谢!

它最终应该在rax中给我什么:0x0000cba 我得到的是0x0000040

enter image description here

1 个答案:

答案 0 :(得分:1)

您似乎使用递归调用的结果部分覆盖当前节点的存储值。我在下面的相关行中添加了星号:

*rmmovq %rax, -10(%rbp)         #the val obtained is stored in -10(%rbp)
 mrmovq -18(%rbp), %rax         #rax becomes ls again
 mrmovq 8(%rax), %rax          # rax gets ls-> next
 rmmovq %rax, %rdi             #this is copied to rdi for next recursive call
 call rsum_list
*rmmovq %rax, -8(%rbp)          #rax will contain ans from recursive call
 mrmovq -10(%rbp), %rdx       #retrieve ans. of current node from -10(%rbbp) , where we stored it before recursion
 mrmovq -8(%rbp), %rax

请注意,两个存储位置相距仅2个字节,但写入的值为8个字节长。鉴于英特尔的小端存储约定,写入将如下对齐,其中列给出在给定递归深度处发生的三次写入的放置(ans表示递归调用的答案)< / p>

RBP: 
 -1:                         ans(MSB)     
 -2:                         ans     
 -3:           ls->val(MSB)  ans     
 -4:           ls->val       ans     
 -5:           ls->val       ans     
 -6:           ls->val       ans     
 -7:           ls->val       ans     
 -8:           ls->val       ans(LSB)
 -9:           ls->val     
-10:           ls->val(LSB)     
-11: ls(MSB)                
-12: ls                
-13: ls                
-14: ls                
-15: ls                
-16: ls                
-17: ls                
-18: ls(LSB)                

不幸的是,单凭这一点不应该产生你的0x40,所以还有别的错误。