You need to know the x86_64 calling convention for SystemV ABI conformant systems (e.g. POSIX/linux) to map the given registers to the arguments in the function prototype. Although this was given as a pre-condition, it's helpful to consult a reference that explains this in more detail: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64
Also, because the code uses %rdi
, we know:
- This is not windows because the windows ABI doesn't use
rdi
for any of its "passed in register" arguments
- We know we're using "AT&T syntax" [because of the
%
prefix] and not "Intel syntax" ...
- ... so the destination register is the rightmost on an instruction.
The "q" suffix on all instructions means "quadword" (i.e. 64 bits). Under windows, long
is 32 bits [go figure :-)], so, again, this is definitely SysV because under windows, the first instruction would a 32 bit one, using the 32 bit register names [and the actual registers would be different]:
subl %edx %esi
Most of the asm instructions should be intuitive.
Note that because of long
, the operations are working on signed integers.
Combining all this, here is a sample program:
// x86_64 calling convention:
// arg 0: %rdi
// arg 1: %rsi
// arg 2: %rdx
// arg 3: %rdx
// arg 4: %r8
// arg 5: %r9
long
foo(long x,long y,long z)
// x -- %rdi
// y -- %rsi
// z -- %rdx
{
long ret;
// subq %rdx %rsi
y -= z;
// imulq %rsi %rdi
x *= y;
// movq %rsi %rax
ret = x;
// salq $63 %rax
ret <<= 63;
// sarq $63 %rax
ret >>= 63;
// xorq %rdi %rax
ret ^= x;
return ret;
}
[Prefaced by the movq
] the two shift operations are a slight "trick".
The first one salq
left shifts bit 0 into bit 63, which is the sign bit. The sarq
is an arithmetic right shift that shifts in the sign bit on the left. The net effect is that all bits will be set to the sign bit.
So, this is equivalent to:
xor_mask = (x & 1) ? -1 : 0;