x86 기계 코드, 39 바이트
;;; Obtain a "reversed" version of the input value.
;;;
;;; To do this, each iteration of a loop, we take the input value modulo 10,
;;; add that to our accumulator (EDI), multiply the accumulator by 10, and
;;; divide the input value by 10. x86's DIV instruction does both modulo and
;;; division as a single operation, with the cost of clobbering two output
;;; registers (EAX and EDX). We clobber the input value throughout the loop
;;; (the way we know we're done is when it becomes 0---that means that we have
;;; pulled all of the digits off of it), so we need to save a copy of it first.
89 C8 mov eax, ecx ; make copy of input
31 FF xor edi, edi ; clear accumulator
6A 0A push 10
5E pop esi ; set ESI to 10
Reverse:
0F AF FE imul edi, esi ; accumulator *= 10
99 cdq ; zero EDX in preparation for division
F7 F6 div esi ; EDX:EAX / 10 (EAX is quot, EDX is rem)
01 D7 add edi, edx ; accumulator += remainder
85 C0 test eax, eax ; was quotient 0?
75 F4 jnz Reverse ; if not, keep looping and extracting digits
;;; At this point, EAX is 0 (clobbered throughout the loop),
;;; ECX still contains a copy of our original input, and
;;; EDI contains the 'reversed' input.
89 C8 mov eax, ecx ; make another copy of the input
F7 E7 mul edi ; multiply input (implicit EAX operand)
; by 'reversed', with result in EDX:EAX
; (note: EDX will be 0)
;;; Compute the greatest common denominator (GCD) of the input and
;;; the 'reversed' values, using a subtraction-based algorithm.
GCD_0:
39 CF cmp edi, ecx ; compare the two values
72 02 jb GCD_1 ; go to GCD_1 if less than
87 F9 xchg ecx, edi ; swap values
GCD_1:
29 F9 sub ecx, edi ; subtract
75 F6 jnz GCD_0 ; if sum != 0, go back to the top
;;; Square the GCD.
0F AF FF imul edi, edi
;;; Divide the product of input and 'reversed' by the square of the GCD.
;;; Remember from above that the product of input and 'reversed' is in
;;; the EAX register, and we can assume EDX is 0, so we don't need to do
;;; a CDQ here in preparation for the division. Using EAX as the implicit
;;; source operand saves us a byte when encoding DIV.
F7 F7 div edi
;;; The DIV instruction placed the quotient in EAX,
;;; which is what we want to return to the caller.
C3 ret
위의 함수는 지정된 입력 매개 변수의 "공통 계수 번호"를 계산합니다. 레지스터 기반 __fastcall 호출 규칙 에 따라 매개 변수가 ECX
레지스터에 전달됩니다 . EAX
모든 x86 호출 규칙과 마찬가지로 결과가 레지스터에 반환됩니다 .
온라인으로 사용해보십시오!
이렇게 컴팩트 한 형식으로 작성하는 데 끔찍한 시간이 걸렸지 만 재미있는 운동이었습니다. x86 DIV
명령어의 암시 적 피연산자의 제약 조건 내에서 MUL
그리고 XCHG
가능한 한 짧은 인코딩 과 명령어 를 사용하려고 할 때 가장 최적의 레지스터 스케줄링을 얻기 위해 많은 왜곡이 발생 합니다. 누군가가 그것을 더 단축시키는 다른 방법을 생각할 수 있는지 궁금합니다. 내 뇌는 결국 튀겨졌습니다. 다음에 컴파일러를 보시면 감사합니다! (이 있지만 방법 이 같은 것들을 제거, 크기 제한없이 약간 불통 특히 경우 ... 컴파일러가 생성하는 것보다 더 나은 코드 XCHG
.)