Home > database >  Int argument passed from C to Assembly loses it's sign
Int argument passed from C to Assembly loses it's sign

Time:06-24

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.

  • Related