Skip to content

Instantly share code, notes, and snippets.

@JohnLaTwC
Created March 17, 2019 18:34
Show Gist options
  • Save JohnLaTwC/e9a2665ce9ae0b460fc4d2f676390f85 to your computer and use it in GitHub Desktop.
Save JohnLaTwC/e9a2665ce9ae0b460fc4d2f676390f85 to your computer and use it in GitHub Desktop.
Fibonacci contest winner
ULONG __declspec(naked) CalcFibMT5 (int dwFibNum)
{
// dwFibNum is passed at esp-4
// Result must be returned in eax
__asm
{
// start pushing working registers ecx, ebx. eax is clobbered
push ecx
mov ecx, round_finish
// retrieve dwFibNum into ecx from stack
mov eax, esp
add eax, 8 // 4 plus a ULONG push
mov eax, [eax] // this is dwFibNum
// work registers: ebx, eax. Final result always ends up in eax
push ebx
// register-register ADD instruction is 2 bytes
shl eax, 1 // each round is 2 bytes, so NOW this is how many instructions we want to execute
sub ecx, eax // walk backward as many instructions as we need
// push our initial state for fib(1) and fib(2)
mov ebx, 1 // load with initial state (eax = 1)
mov eax, 1 // our initial answer
jmp ecx // and jump to our computation
// round_start:
// 48
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 46
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 44
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 42
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 40
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 38
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 36
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 34
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 32
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 30
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 28
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 26
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 24
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 22
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 20
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 18
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 16
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 14
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 12
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 10
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 8
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 6
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// 4
add ebx, eax // result of 1st round stored in ebx
add eax, ebx // result of 2nd round stored in eax
// oh, what a tangled web we weave
// when first we practice to deceive
// this is NEVER executed as 4 noops
// it is mov ecx, 0x90908bff
// or mov esi, esi
// depending on where you jump into it
_emit 0xb9
_emit 0x90
_emit 0x90
_emit 0x8b
round_finish:
_emit 0xf6
// the 'straightforward' version
// 2
// nop
// nop
// 1
// nop
// nop
// result in eax
pop ebx
pop ecx
ret 4
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment