[C-prog-lang-l] integer promotion in x86 assembly

Vladimír Kotal vlada at kotalovi.cz
Mon Mar 14 21:02:43 CET 2022


Hi all,

for those of you who want to see how are the integer operations done in practice on concrete architecture/implementation, the following are my notes from Clang on x64/macOS for integer promotion:

When a `short` or `char` is converted to `int`, the promotion preserves the sign and the value. On x86 this happens via Sign extension <https://en.wikipedia.org/wiki/Sign_extension>.

Using `src/int-promotion.c`:

`(lldb) list
   5   	{
   6   		unsigned char a = 0xff;
   7   		/*
   8   		 * This will probably wrap around and is implementation defined by the
   9   		 * spec.
   10  		 */
   11  		signed char b = 0xff;
   12  	
   13  		int c = (a == b); // true, or false ?
   14  	
(lldb) b 13
Breakpoint 1: where = int-promotion`main + 30 at int-promotion.c:13, address = 0x0000000100000efe
(lldb) r
Process 76793 launched: './int-promotion' (x86_64)
Process 76793 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100000efe int-promotion`main at int-promotion.c:13
   10  		 */
   11  		signed char b = 0xff;
   12  	
-> 13  		int c = (a == b); // true, or false ?
   14  	
   15  		/*
   16  		 * Note that 'a' and 'b' are first promoted to ints (integer promotion)
Target 0: (int-promotion) stopped.
(lldb) p/x a
(unsigned char) $1 = 0xff
(lldb) p/x b
(signed char) $2 = 0xff
(lldb) disassemble 
int-promotion`main:
    0x100000ee0 <+0>:   pushq  %rbp
    0x100000ee1 <+1>:   movq   %rsp, %rbp
    0x100000ee4 <+4>:   subq   $0x20, %rsp
    0x100000ee8 <+8>:   leaq   0x8f(%rip), %rdi          ; "a: %hhu, b: %hhd\n"
    0x100000eef <+15>:  movl   $0x0, -0x4(%rbp)
    0x100000ef6 <+22>:  movb   $-0x1, -0x5(%rbp)
    0x100000efa <+26>:  movb   $-0x1, -0x6(%rbp)
->  0x100000efe <+30>:  movzbl -0x5(%rbp), %eax
    0x100000f02 <+34>:  movsbl -0x6(%rbp), %ecx
    0x100000f06 <+38>:  cmpl   %ecx, %eax
...
`
The `movsbl` is move with sign extension, used to promote `b`. The `movzbl` is move with zero fill, used to promote `a`. Both move to 32-bit registers.

Stepping 2 assembler instructions:

`(lldb) stepi
...
(lldb) stepi
...
(lldb) register read eax ecx
     eax = 0x000000ff
     ecx = 0xffffffff
`
-------------- next part --------------
HTML attachment scrubbed and removed


More information about the c-prog-lang-l mailing list