I know that function arguments are padded to target word size, but with what?
Specifically in the context of the x86 Linux GNU toolchain, what do these functions return?
int iMysteryMeat(short x)
{
return *((int *)&x);
}
unsigned uMysteryMeat(unsigned short x)
{
return *((unsigned *)&x);
}
The question is whether, when hand-coding a function in assembly, it is necessary to sterilze “small” arguments by masking or sign-extending them before using them in “large” contexts (andl, imull).
I’d also be interested whether there are any more general or cross-platform standards for this case.
This depends on the ABI. The ABI needs to specify the choice that small arguments are extended by the caller, or by the callee (and how). Unfortunately, this part of the ABI is often underspecified, leading to different choices by different compilers. So to prevent incompatibility between code compiled with different legacy compilers, most modern compilers (I know in particular about
gcconi386) err on the side of caution and do both.Note that
adoes not assume any extension rule about its argument, but extends it itself. Similarly,cmakes sure to extend its argument before passing it tob(via a tail call).