Hi there,

I'm just run into a wicked C compiler issue, made from Visual Studio 2008 in x64 compile mode.

C Code:

unsigned char * screen ;
unsigned char * target ;
int offsetx, offsety, pitch ;

target = & screen ;


Compiles to this ASM code:

mov ecx, <calculation of offsety * pitch + offsetx>
mov rax, screen
add rax, rcx
mov target, rax


This fails greatly if offset is a negative number. Also the compiler does not clear the upper 32 bit of rcx, so they could be undefined.

Is this a bug or a feature? And how can I make the compiler handle my array index on the 64 bit pointer correctly?
Posted on 2013-02-15 03:55:50 by beaster
Also the compiler does not clear the upper 32 bit of rcx, so they could be undefined.
It does, if the "mov ecx, ..." instruction you showed is more or less real (the processor always clears the upper half of 64 bit registers when the lower half is the destination operand of an instruction).

Could you show more disassembly? The first instruction doesn't seem possible unless the compiler deduced that the three variables will always have the same value. In such case, you could try using "volatile int offsetx, offsety, pitch ;" one time to see if that makes any difference or just feed the variables from the stdin so the compiler cannot assume non-negetive numbers.
Posted on 2013-02-15 06:07:16 by LocoDelAssembly
you are right, moving 32 bit registers clears the upper area.

The problem with the negative value occurs only if one of the operands is unsigned:


unsigned int pitch ;
int offsety, offsetx ;
unsigned char * screen ;
unsigned char * target ;

target = & screen ;


seems to make the whole offset calculation unsigned and negative values for offsetx/offsety give wrong 64 bit result:


000000013F4A104A  mov        eax,dword ptr
000000013F4A104E  imul        eax,dword ptr
000000013F4A1052  add        eax,dword ptr
000000013F4A1056  mov        ecx,eax
000000013F4A1058  mov        rax,qword ptr
000000013F4A105D  add        rax,rcx
000000013F4A1060  mov        qword ptr ,rax


Solution: making all operands signed, gives the expected compilation:


int pitch ;
int offsety, offsetx ;
unsigned char * screen ;
unsigned char * target ;

target = & screen ;


asm contains the expected movsxd:


000000013F0A104A  mov        eax,dword ptr
000000013F0A104E  imul        eax,dword ptr
000000013F0A1052  add        eax,dword ptr
000000013F0A1056  movsxd      rcx,eax
000000013F0A1059  mov        rax,qword ptr
000000013F0A105E  add        rax,rcx
000000013F0A1061  mov        qword ptr ,rax
Posted on 2013-02-15 06:33:59 by beaster