I am trying to implement a sign function in assembly(64 bit) and then calling it from C. My function takes in one argument: an unsigned int and returns an int, which can be -1 (if the argument is negative), 0 (if the argument is 0), and 1 (if the argument is positive).
My program works well for detecting positive numbers and zero but if I pass a negative number as the argument then it handles it as a positive one and returns 1.
main.c:
#include <stdio.h>
extern int sign(signed int);
int main()
{
signed int num;
scanf("%d",&num);
printf("num: %d sign: %d\n",num,sign(num));
return 0;
}
sign.asm:
global sign
section .text
sign:
test rdi,rdi
js neg_lab
je zero_lab
mov rax,1
jmp end_lab
neg_lab:
mov rax,-1
jmp end_lab
zero_lab:
xor rax,rax
end_lab:
ret
At first I taught that the problem is in the assembly code, so i set the tested registers value to a positive number then a negative number and finally to zero. It worked well. It recognized negative numbers too. After this I think the problem is with the passing of arguments. I think the sign of the arguments is getting lost somewhere, or C way of storing negative number is just not compatible with assembly?
I would appreciate any help. Thank you in advance!
CodePudding user response:
This is because you have declared your function to take a 32 bit integer but implemented it to work on 64 bit integers. So when you pass, say -1
, to the function, it actually receives 0x00000000ffffffff
instead of 0xffffffffffffffff
as you might expect.
There are two ways to fix this:
Either, rewrite the declaration to use 64 bit integers:
extern long long sign(unsigned long long);
or rewrite the code to use 32 bit integers, e.g. like this:
global sign
section .text
sign:
test edi,edi
js neg_lab
je zero_lab
mov eax,1
jmp end_lab
neg_lab:
mov eax,-1
jmp end_lab
zero_lab:
xor eax,eax
end_lab:
ret
Note that return value and argument can have their sizes decided independently. They don't have to have the same size.