2

I don't know what the problem is because this works perfectly for SIN and COS. For TAN, it returns 0.0000 for 50.0 radian. But if I enabled the commented line, it works as expected. That's weird because TAN is supposed to return a double in XMM0, not RAX.

;./fasm testing.asm
;gcc -s testing.o -o testing -lm
format elf64
extrn printf
extrn tan

section '.data' writeable align 16
rad dq 50.0
fmt db "%.5lf",0ah,0

section '.text' executable align 16
public main
main:
    push rbp
    mov rbp,rsp

    pxor xmm0,xmm0
    movq xmm0,[rad]
    call tan
    ;movq rax,xmm0  ;works if I enable this. but SIN and COS don't need this
    mov rdi,fmt
    call printf

    mov rsp,rbp
    pop rbp
    ret

What could be the problem here?

royalfinest
  • 155
  • 1
  • 8

1 Answers1

2

When calling any function in x86-64 assembly, AL must contain the number of registers used. It's the convention, you can't avoid it.

Variable-argument subroutines require a value in RAX for the number of vector registers used.

RAX is a temporary register; with variable arguments passes information about the number of vector registers used; 1st return register.

You can consult the System V Application Binary Interface, chapter 3.2.3 Parameter Passing.

Therefore, you need to specify the number of parameters you use in rax.

movq rax, 1

should suffice.

user35443
  • 6,309
  • 12
  • 52
  • 75
  • Did u mean "mov rax,1"? Thank you for the answer. But the issue is, I don't need to explicitly set RAX to 1 when using SIN and COS. – royalfinest Jun 07 '15 at 11:48
  • `movq` and `mov` are just alternatives. Anyway, you don't need it, because `sin` and `cos` don't have variable number of parameters, as for example `printf` does; they just need a single input, that's why they don't require `1` in `rax`. – user35443 Jun 07 '15 at 11:54
  • I am confused, bro. Are u suggesting TAN needs RAX=1 as well? – royalfinest Jun 07 '15 at 11:57
  • No, I'm saying that `tan` doesn't. The commented `movq rax,xmm0` is executed *after* a call to `tan` happens. It *doesn't* affect `tan`, but the `printf` call after it. – user35443 Jun 07 '15 at 11:59
  • This is confusing bro. I know what you mean by that, but that doesn't explain why SIN and COS work just fine even without setting RAX=1 before calling printf. They return in XMM0 just as expected. – royalfinest Jun 07 '15 at 12:03
  • 1
    @royalfinest The function that is called before `printf` is not related to what `printf` outputs. Every `printf` requires the number of arguments to be stored in `rax`. If - by luck - it happens that you don't need to input `rax` before calling it, it's just because of the random garbage in it, and it's not what you should rely on, as in other cases the garbage could be confindently equal to `0`. – user35443 Jun 07 '15 at 12:06
  • Ok bro. That could explain it. Thanks for your useful answers. – royalfinest Jun 07 '15 at 12:09