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つがアキュムレータである場合は前者が1バイトであるのに対し、レジスタとレジスタMOVは常に2バイトである)を除いては優先されません。