Home > Net >  Converting a signed int32 to an unsigned int64
Converting a signed int32 to an unsigned int64

Time:11-20

int main(){
  unsigned long a = 5;
  int b = -6;

  long c = a   b;

  return 0;
}

I wanted to follow the rules explined in this link and confirm my understanding of how the compiler emits code for a b: https://en.cppreference.com/w/c/language/conversion

1- b is first converted to an unsigned long:

If the unsigned type has conversion rank greater than or equal to the rank of the signed type, then the operand with the signed type is implicitly converted to the unsigned type.

So the the compiler essentially does this:

unsigned long implicit_conversion_of_b = (unsigned long) b;

2- The above implicit conversion itself is covered with this rule under Integer conversions:

if the target type is unsigned, the value 2b , where b is the number of bits in the target type, is repeatedly subtracted or added to the source value until the result fits in the target type.

3- We finlay end up with these 64-bit values in a register before addition takes place:

a = 0x5
b = 0xfffffffffffffffa

Is the above a correct mapping to the rules?

Edit:

4- The final result is an unsigned long which needs to be converted to long needed b c using this rule:

otherwise, if the target type is signed, the behavior is implementation-defined (which may include raising a signal)

CodePudding user response:

Is the above a correct mapping to the rules?

Yes.

CodePudding user response:

I'm certainly no assembly expert, but it's interesting to see what's happening here. Compiled with gcc -O0:

main:
        // setup stack
        push    rbp
        mov     rbp, rsp
        // move 5 into 8-byte offset from the stack frame.
        // rbp is the stack frame pointer, offset of 8 shows long is 8
        // bytes on this architecture
        mov     QWORD PTR [rbp-8], 5
        // move -6 to 12 bytes offset from rbp (or 4 byte offset from
        // last value. This tells you int is 4 bytes on this architecture.
        mov     DWORD PTR [rbp-12], -6
        // move the int into eax register. This is a 32-bit general
        // purpose register
        mov     eax, DWORD PTR [rbp-12]
        // movsx is a "move with sign extension" instruction. rdx is a
        // 64-bit register, so this is your conversion from 32 to 64
        // bits, preserving the sign
        movsx   rdx, eax
        // moves 5 to the 64-bit rax register
        mov     rax, QWORD PTR [rbp-8]
        // performs the 64-bit add
        add     rax, rdx
        // not using the result, so cleanup, prepare to return
        // from function
        mov     QWORD PTR [rbp-24], rax
        mov     eax, 0
        pop     rbp
        ret

This assembly was generated with gcc 11.2

  •  Tags:  
  • c
  • Related