8086 머신 코드, 27 바이트
00000000 bb 00 00 85 c0 74 13 01 d8 be 00 01 89 e7 47 47 |.....t........GG|
00000010 57 b9 1b 00 f3 a4 5b 89 47 01 c3 |W.....[.G..|
0000001b
이 기계 코드는 주소 0x100에 있어야하며 작은 코드 모델 (cs = ds = es = ss)을 가정합니다. 그러나 추가 바이트 비용없이 함수 위치를 변경할 수 있습니다. 오프셋에 넣으면 0
바이트가 절약 xor si,si
됩니다 ( 대신 mov si, 0x100
)
필요한 통화 규칙
이것은 호출자가 스택에서 최소 27 바이트를 미리 할당했다고 가정합니다. 에 숫자를 사용 ax
하고에 함수 포인터를 반환합니다 bx
. 로이 포인터를 호출 ax=0
하면 체인 이 종료되고에 합계가 반환됩니다 bx
.
첫 번째 전화의 경우 :
mov bp, sp
sub sp, 28
mov ax, number_to_add
call function
; new function pointer in bx
그런 다음 각 후속 호출에 대해 다음을 수행하십시오.
sub sp, 28
mov ax, number_to_add
call bx
; new function pointer in bx
종료하려면 :
mov ax, 0
call bx
; result in bx
mov sp, bp
Ungolfed (기계 코드의 주석 처리 된 분해) :
00000000 BB0000 mov bx,0x0 ; 0 is replaced after copying
00000003 85C0 test ax,ax
00000005 7413 jz 0x1a ; if(ax==0) ret (with value in bx)
00000007 01D8 add ax,bx ; arg += total
00000009 BE0001 mov si,0x100 ; address of the original: ds:0x100
0000000C 89E7 mov di,sp
0000000E 47 inc di
0000000F 47 inc di ; dst = sp+2 = above return address
00000010 57 push di
00000011 B91B00 mov cx,0x1b
00000014 F3A4 rep movsb ; copy the function code.
00000016 5B pop bx ; bx = start of copy destination
00000017 894701 mov [bx+0x1],ax ; update total in the copied code
0000001A C3 ret ; with bx = function pointer
0이 아닌 AX로 이것을 호출 bx = sp
하면 버퍼는의 머신 코드의 수정 된 사본으로 채워집니다 function
. 첫 번째 명령어의 16 비트 즉시 합계가 유지됩니다. (이전의 마지막 명령으로 작성되었습니다 ret
.)
push di
/ pop bx
를 mov bx, di
(이전 rep movsb
) 로 대체하여 더 간단하지만 비용을 절감 할 수는 없습니다.
호출자가 dst 버퍼에 포인터를 전달하도록 요구 di
4 바이트를 절약 할 수 sp
있습니다.
함수 시작 주소를 함수 크기와 동일하게하면 바이트 ( mov cx, si
) 가 절약 됩니다.
f(4)
새 함수 를 반환 한다는 의미입니다 . 새 함수가 인수없이 호출되면이 함수는을 반환4
하지만 다른 인수로 호출 된 경우 동일한 의미론을 갖지만 새 인수가 추가 된 등의 새로운 함수를 다시 반환합니다4
.