title: Assembly early return on a recursive function
body: <p>This is more an academic exercise than anything else, but I'm looking to write a recursive function in assembly, that, if it receives and &quot;interrupt signal&quot; it returns to the main function, and not just the function that invoked it (which is usually the same recursive function).</p>
  <p>For this test, I'm doing a basic countdown and printing one-character digits (8...7...6...etc.). To simulate an &quot;interrupt&quot;, I am using the number <code>7</code>, so when the function hits 7 (if it starts above that), it will return a <code>1</code> meaning it was interrupted, and if it wasn't interrupted, it'll countdown to zero. Here is what I have thus far:</p>
  <pre><code>.globl _start
  _start:
  
      # countdown(9);
      mov $8, %rdi
      call countdown
  
      # return 0;
      mov %eax, %edi
      mov $60, %eax
      syscall
  
  print:
      push %rbp
      mov %rsp, %rbp
  
      # write the value to a memory location
      pushq %rdi # now 16-byte aligned
      add $'0', -8(%rbp)
      movb $'\n', -7(%rbp)
  
      # do a write syscall
      mov $1, %rax        # linux syscall write
      mov $1, %rdi        # file descriptor: stdout=1
      lea -8(%rbp), %rsi  # memory location of string goes in rsi
      mov $2, %rdx        # length: 1 char + newline
      syscall
  
      # restore the stack
      pop %rdi
      pop %rbp
      ret;
  
  countdown:
      # this is the handler to call the recursive function so it can
      # pass the address to jump back to in an interrupt as one of the
      # function parameters
      # (%rsp) currntly holds the return address, and let's pass that as the second argument
      mov %rdi, %rdi      # redundant, but for clarity
      mov (%rsp), %rsi    # return address to jump
      call countdown_recursive
  
  
  countdown_recursive:
  
      # bool countdown(int n: n&lt;10, return_address)
  
      # ...{
      push %rbp
      mov %rsp, %rbp
  
      # if (num&lt;0) ... return
      cmp $0, %rdi
      jz end
  
      # imaginary interrupt on num=7
      cmp $7, %rdi
      jz fast_ret
  
      # else...printf(&quot;%d\n&quot;, num);
      push %rsi
      push %rdi
      call print
      pop %rdi
      pop %rsi
  
      # --num
      dec %rdi
  
      # countdown(num)
      call countdown_recursive
  
  end:
      # ...}
      mov $0, %eax
      mov %rbp, %rsp
      pop %rbp
      ret
  
  fast_ret:
      mov $1, %eax
      jmp *%rsi
  </code></pre>
  <p>Does the above look like a valid approach, passing the memory address I want to go back to in <code>rsi</code>? The function was incredibly tricky for me to write, but I think mainly due to the fact that I'm pretty new/raw with assembly.</p>