FILD, FSTP and FST assembly instructions
===

So I have been solving [this][1] crackme today. I managed to locate and understand the serial generating routine except for a few last instructions. I decided to write a keygen **in assembly for the first time**. Everything was going nicely until I came to the last few instructions of the serial routine. I'm using MASM and Intel assembly (Intel, AT&T, how do you call these?) This is my current code:

	.386
	.model flat,stdcall
	option casemap:none

	include 	\masm32\include\windows.inc
	include 	\masm32\include\kernel32.inc
	include 	\masm32\include\user32.inc
	includelib 	\masm32\lib\kernel32.lib
	includelib 	\masm32\lib\user32.lib

	DlgProc 	proto :DWORD,:DWORD,:DWORD,:DWORD
	SerialCalc 	proto :DWORD

	.data
	EnterText	db		"...enter a name...",0
	temp		db		"temp",0
	Format		db 		"%i-x019871",0

	.data?
	NameBuffer		db 			100 dup(?)
	SerialBuffer	db			150 dup(?)
	SerialLength	dd			?
	hInstance 		HINSTANCE 	?

	.const
	IDC_NAME 			equ 	1002
	IDC_SERIAL 			equ 	1003
	IDC_GENERATE 		equ 	1004
	IDC_NAMELABEL 		equ 	1005
	IDC_SERIALLABEL 	equ 	1006
	IDD_MAIN 			equ 	1001

	.code
	start:

		invoke GetModuleHandle, NULL
		mov hInstance,eax
		invoke DialogBoxParam, hInstance, IDD_MAIN, NULL, addr DlgProc, NULL
		invoke ExitProcess, 0
		
	DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
		.if uMsg == WM_INITDIALOG
			invoke GetDlgItem,hWnd,IDC_NAME ;get IDC_NAME
			invoke SetFocus,eax				;focus on it
		.elseif uMsg == WM_COMMAND
			mov eax, wParam ;wParam = control that issued the WM_COMMAND message
			.if ax == IDC_NAME ;if it was the name box
				shr eax, 16 ;shift right and get more info?
				.if ax == EN_CHANGE ;if the text was changed
					invoke GetDlgItemText, hWnd, IDC_NAME, addr NameBuffer, 100 ;get text
					invoke lstrlen, addr NameBuffer	;get length
					mov SerialLength, eax ;move length into var
					.if eax == 0 ;if length is 0
						invoke SetDlgItemTextA, hWnd, IDC_SERIAL, addr EnterText ;"...enter a name..."
					.elseif eax > 0 ;if length is bigger than 0
						invoke SerialCalc, hWnd ;calc
						invoke SetDlgItemTextA, hWnd, IDC_SERIAL, addr SerialBuffer ;"serial"
					.endif
				.endif
			.endif
		.elseif uMsg == WM_CLOSE
			invoke EndDialog, hWnd, 0
		.endif
		
		xor eax,eax
		ret
	DlgProc endp

	SerialCalc proc hWnd:HWND
		;push ecx allocate space for 1 local variable; i was trying to do something with local variables, but I failed
		mov edx, SerialLength
		imul edx, edx, 875CDh
		mov eax, 51EB851Fh
		mul edx
		mov eax, edx
		shr eax, 5h
		imul eax, eax, -370h
		xor edx, edx ;mov edx, 0
		;problems start here; I took this code from a solution i found
		;push edx
		;push eax
		;fild qword ptr [esp]
		;add esp, 8
		;ftsp real8 ptr [SerialBuffer]
	SerialCalc endp

	end start

And this is the actual serial routine in the program itself:

	MOV EDX,EAX
	IMUL EDX,EDX,875CD
	MOV EAX,51EB851F
	MUL EDX
	MOV EAX,EDX
	SHR EAX,5
	IMUL EAX,EAX,-370
	MOV EDX,0
	PUSH EDX                                                            ; ||format = NULL
	PUSH EAX                                                            ; ||s = FE8BC1A0
	FILD QWORD PTR SS:[ESP]                                             ; ||
	LEA ESP,DWORD PTR SS:[ESP+8]                                        ; ||
	FSTP QWORD PTR SS:[EBP-410]                                         ; ||
	FLD QWORD PTR SS:[EBP-410]                                          ; ||
	FSTP QWORD PTR SS:[ESP+8]                                           ; ||
	MOV DWORD PTR SS:[ESP+4],Crackme_.00401469                          ; ||ASCII "%i-x019871"
	LEA EAX,[LOCAL.194]                                                 ; ||
	MOV DWORD PTR SS:[ESP],EAX                                          ; ||
	CALL <JMP.&msvcrt.sprintf>                                          ; |\sprintf
	LEA EAX,[LOCAL.194]                                                 ; |
	MOV DWORD PTR SS:[ESP+4],EAX                                        ; |
	LEA EAX,[LOCAL.130]                                                 ; |
	MOV DWORD PTR SS:[ESP],EAX                                          ; |
	CALL <JMP.&msvcrt.strcmp>                                           ; \strcmp



The routine calculates the serial which finishes in EAX, pushes it onto the stack and then, as far as I understand, uses FILD to push it onto the FPU stack, FSPT to take it off of the FPU and put it into EBP-410, FLD to push EBP-410 onto the FPU again and finally, uses the FSTP to store it into ESP+8 as a parameter for sprintf. The sprint and strcmp don't really matter here but I included them anyway so you can get a better understanding of what's going on.

By the way, this LOCAL 194. is the place where the formatted string will be placed.

I searched the Internet and found these instructions' descriptions but haven't found any actual examples or material that could help me transfer this to my keygen.

So the final question is: how do I transfer this to my keygen? The commented stuff in my SerialCalc routine is the part which I ripped off of another guy's solution just to try if it'll work, but unfortunately, it didn't.

Tell me if you need more details about the problem or any extra information.

I apologize for my noobiness!

Thanks in advance,
Tuntuni.

  [1]: http://crackmes.de/users/lucifer/first_c_crackme/