1

im trying to do a simple program calculating a recursive function where:

  1. X1 = -1
  2. X2 = -2
  3. Xn = X(n-1) * X(n-2)

Using x64 assembly. I have two problems i cant come up with solution for:

  • a) how can i make it like a "real" function - argument passed in %rax, function result located in %rax. As you can see for now my argument is passed through %rdi and result is in %rax.
  • b) how can i pass the argument and results through stack? i tried it but failed (stack-version lines are commented out). it has something to do with calculating address i suppose, could someone modify it so i get the grasp how it should have been done?

    .data
    SYSREAD = 0
    SYSWRITE = 1
    SYSEXIT = 60
    NUMBER = 4
    
    STDOUT = 1 
    STDIN = 0
    
    EXIT_SUCCESS = 0
    
    .text
    .global main
    
     main:
    # --- --- --- --- --- --- --- --- --- --- --- ---
    mov $0, %rax
    mov $0, %r15
    mov $0, %rdi
    mov $NUMBER, %rdi
    
    # push %rdi
    call recursion
    # pop %rax
    jmp end
    
    # --- --- --- --- --- --- --- --- --- --- --- ---
                                    # function
                                    # X1 = -1
                                    # X2 = -2
                                    # Xn = X(n-1) razy X(n-2)
                                    # input   => %rax = n
                                    # output  => %rax = X(n)
    recursion:
    # pop %rdi
    
    cmp $1, %rdi                    # is n = 1? 
    je recursion_end_1
    
    cmp $2, %rdi                    # is n = 2?
    je recursion_end_2
                                    # n in %rdi
    dec %rdi                        # (n-1)
    push %rdi                       # (n-1) into stack
    call recursion
    
    pop %rdi                        # (n-1) in %rdi
    dec %rdi                        # (n-2)
    push %rax                       # (n-2) into stack
    call recursion
    
    pop %rcx                        # value of (n-2)
    imul %rcx                       # multiplication
    push %rax
    jmp recursion_end               # result in %rax
    
    recursion_end_1:
    mov $-1, %rax                   # n = 1
    ret
    
    recursion_end_2:
    mov $-2, %rax                   # n = 2
    ret
    
    recursion_end:
    ret
    
    # --- --- --- --- --- --- --- --- --- --- --- ---
    
    end:
    movq $SYSEXIT, %rax             # wychodzenie
    movq $EXIT_SUCCESS, %rdi
    syscall
    
JPK
  • 23
  • 3
  • 2
    "real" functions **do** get the first argument in `rdi` as per the normal sysv abi convention. – Jester May 09 '17 at 22:37
  • About stack: http://stackoverflow.com/q/1395591/4271923 By the very first `pop %rdi` inside `recursion` you are taking return address out of stack, not argument (arguments are above that, so `mov rdi,[rsp+8]` is probably close to what you want). Don't hesitate to step into this code in debugger, and watch values in `rsp` + open memory window to that area, to see how those values are written into memory + how `push/pop/call/ret` operates. Every minute of poking around in debugger usually equals to 10 minutes of reading/explaining. – Ped7g May 10 '17 at 13:27

0 Answers0