Is this the rigth way to write power and factorial functions with nasm? I wrote factorial and power functions with nasm but I don't know if it is the right to write assembly code. For example, by executing the functions I make some changes in the registers and I don't know if I have to revert them to their original value a the end with push and pop.

To write the factorial function, I first wrote it in C, compiled it with gcc and disassembled it with gdb. It gave me inspiration to write the code. Then I followed the same way of coding for my power function.

I use 64 bits registers.

Here is my code :

; Factorial function n!
; Argument from rsi and return in rax
factorial:
  push rbp
  mov rbp, rsp

  sub rsp, 0x10 ; Allocate 2 bytes on the stack
  mov DWORD [rbp-4], esi ; Put the parameter on the stack
  cmp DWORD [rbp-4], 1 ; if ==1 there is nothing to do
  jne factorial_rec
  mov eax, 1 ; return 1
  jmp fin_factorial
factorial_rec:
  mov eax, DWORD [rbp-4] ; Move the parameter in eax
  sub eax, 1
  mov esi, eax
  call factorial ;Call factorial recursively with eax-1
  imul eax, DWORD [rbp-4] ; multiply eax by the parameter
fin_factorial:
  leave
  ret

; Power function x^n
; Argument from rsi and rdi return in rax
; rsi at the power rdi
power:
  push rbp
  mov rbp, rsp

  cmp rdi, 0 ; if == 0
  jne power_init
  mov eax, 1 ; Return 1 (x^0=1)
  jmp power_end
power_init:
  sub rsp, 0x10 ; Allocate 2 bytes on the stack
  mov DWORD [rbp-4], esi ; Put the parameter on the stack
  mov eax, esi ; first power
power_loop:
  dec edi
  cmp edi, 0
  je power_end
  imul eax,DWORD[rbp-4] ; Multiply eax by the parameter until edi == 0
  jmp power_loop
power_end:
  leave
  ret


Thank you for your comments.
sub rsp, 0x10 ; Allocate 2 bytes on the stack



The comment is not correct! 0x10 is an hexadecimal number equal to 16 in decimal.


cmp rdi, 0 ; if == 0
jne power_init



If you need to compare with zero, it's usually better to test the register to itself:

test rdi, rdi
jnz  power_init



dec edi
cmp edi, 0
je power_end



The cmp edi, 0 instruction is redundant since the dec edi instruction already provides the necessary zero condition status.




  For example, by executing the functions I make some changes in the registers and I don't know if I have to revert them to their original value a the end with push and pop.


If you write these functions and your program uses these functions, then it's up to you to decide if you deem it useful to preserve any or all of the registers. If someone else will be using your functions your comments should make it absolutely clear what registers get clobbered!



The recursive factorial function can do without the prologue/epilogue code and is a bit complicated.

; IN (esi) OUT (eax) MOD ()
; Calculate eax = esi!
Factorial:
    mov  eax, 1
    cmp  esi, eax
    je   .return       ; esi was 1 -&gt; eax = 1
    push esi           ; (1)
    dec  esi
    call Factorial     ; -&gt; EAX
    pop  esi           ; (1)
    imul eax, esi
.return:
    ret


The power function can do without the prologue/epilogue code. There's no need to put ESI on the stack. If you want you could preserve the EDI register, but that's up to you to decide.

; IN (esi,edi) OUT (eax) MOD (edi)
; Calculate eax = esi ^ edi
Power:
                      ; push edi
    mov  eax, 1
    sub  edi, eax
    jb   .return      ; edi was 0 -&gt; eax = esi^0 = 1
    mov  eax, esi
    jz   .return      ; edi was 1 -&gt; eax = esi^1 = esi
.more:
    imul eax, esi
    dec  edi
    jnz  .more
.return
                      ; pop edi
    ret