x86-64机器码,18字节
97
99
31 D0
29 D0
99
F7 FE
29 D6
A8 01
0F 45 D6
92
C3
这段代码使用x86-64机器语言定义了一个计算的函数bounce(x, k
。遵循Gnu / Unix系统上使用的System V AMD64调用约定,x
参数在EDI
寄存器中传递,而k
参数在ESI
寄存器中传递。与所有x86调用约定一样,结果将返回到EAX
寄存器中。
要从C调用此函数,您可以将其原型如下:
int Bounce(int x, int k);
在线尝试!
非高尔夫装配助记符:
; Take absolute value of input 'x' (passed in EDI register).
; (Compensates for the fact that IDIV on x86 returns a remainder with the dividend's sign,
; whereas we want 'modulo' behavior---the result should be positive.)
xchg eax, edi ; swap EDI and EAX (put 'x' in EAX)
cdq ; sign-extend EAX to EDX:EAX, effectively putting sign bit in EDX
xor eax, edx ; EAX ^= EDX
sub eax, edx ; EAX -= EDX
; Divide EDX:EAX by 'k' (passed in ESI register).
; The quotient will be in EAX, and the remainder will be in EDX.
; (We know that EAX is positive here, so we'd normally just zero EDX before division,
; but XOR is 2 bytes whereas CDQ is 1 byte, so it wins out.)
cdq
idiv esi
; Pre-emptively subtract the remainder (EDX) from 'k' (ESI),
; leaving result in ESI. We'll either use this below, or ignore it.
sub esi, edx
; Test the LSB of the quotient to see if it is an even number (i.e., divisible by 2).
; If not (quotient is odd), then we want to use ESI, so put it in EDX.
; Otherwise (quotient is even), leave EDX alone.
test al, 1
cmovnz edx, esi
; Finally, swap EDX and EAX to get the return value in EAX.
xchg eax, edx
ret
请注意,第一部分(采用绝对值)可以等效地编写为:
; Alternative implementation of absolute value
xchg eax, edi
neg eax
cmovl eax, edi
完全相同的字节数(6)。性能应该相似,也许会稍快(有条件移动较慢的某些Intel芯片除外)。
XCHG
当然,它是相对较慢的,MOV
除了在代码打高尔夫球中(在操作数之一是累加器的情况下,前者是1字节,而在寄存器中的寄存器MOV
始终是2字节)时,它是不可比的。