Please help with ASM question

Started by
4 comments, last by DividedByZero 6 years ago

Hi Guys,

I am currently playing around with MASM and am currently stumped on how to implement my frame rate counter.

The problem is caused by QueryPerformanceCounter returning a LONG INTEGER which is 64 bits in length. So I am struggling to work out how to calculate a few things.

This is what I have ported over so far from my C/C++ code.

 



invoke QueryPerformanceFrequency, addr TimeFrequency
invoke QueryPerformanceCounter, addr TimeEnd

;TimeElapsed.QuadPart = TimeEnd.QuadPart - TimeStart.QuadPart;
mov eax,DWORD PTR TimeEnd[0]
sub eax,DWORD PTR TimeStart[0]
mov ecx,DWORD PTR TimeEnd[+4]
sbb ecx,DWORD PTR TimeStart[+4]
mov DWORD PTR TimeElapsed[0], eax
mov DWORD PTR TimeElapsed[+4], ecx   // I think this is correct up to here

;TimeElapsed.QuadPart *= 1000000000; // **** Not sure what to do here		
;TimeElapsed.QuadPart /= TimeFrequency.QuadPart; // **** Not sure what to do here

inc nCounter

;if (TimeElapsed.QuadPart > 1000000000)  // *** Not sure what to do here
.if 1		; placeholder
	invoke itoa, nCounter, addr szBuffer, 10
	invoke SetWindowText, hWnd, addr szBuffer
	mov nCounter, 0
	invoke QueryPerformanceFrequency, addr TimeFrequency
	invoke QueryPerformanceCounter, addr TimeStart
.endif

 

Any help would be absolutely awesome!

Thanks in advance :D

 

Advertisement

Do you have access to 64-bit operations? That would simplify things a bit, as 64-bit versions of imul, idiv and cmp solve problem quite straightforwardly.

If this is purely 32-bit code you need to construct them from 32-bit pieces.

If you're not in the mood to try to figure it out yourself, you can just copy the C++ code into gcc.godbolt.org, and see what compilers do in this situation:

https://godbolt.org/g/2F9a1e

As you can see, the division is especially heavy (multpliy and compare are relatively easy: "imul+mul+add" and "cmp 0+cmp 1000000000" respectively). Compilers just implement it as a function call.

The code for __divdi3 can be seen here:

https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/wordsize-32/divdi3.c;h=257d93cc37c011f2714b48ccb0c476f5a4a39319;hb=HEAD

Thanks for the reply. Actually I got this working about an hour after posting, apologies for not replying back then.


		invoke QueryPerformanceFrequency, addr TimeFrequency
		invoke QueryPerformanceCounter, addr TimeEnd
		fild TimeEnd
		fild TimeStart
		fsub
		fild TimeNanoSecond
		fmul
		fild TimeFrequency
		fdiv
		fistp TimeElapsed
		
  		inc nCounter
		
		mov eax, DWORD PTR TimeElapsed[0]
		mov ebx, 1000000000
		cmp eax, ebx
		jl skip
			invoke itoa, nCounter, addr szBuffer, 10
			invoke SetWindowText, hWnd, addr szBuffer
			mov nCounter, 0
			invoke QueryPerformanceFrequency, addr TimeFrequency
			invoke QueryPerformanceCounter, addr TimeStart
		skip:

 

Yes, float works too. I was about to reply that.

Actually, FIDIV, FIMUL, and FISUB might make the code a bit smaller.

Also note, that you can (I think) force FDIV to produce the same result as integer division (by setting precision to full (64-bit mantissa), and rounding to RoundToZero (i.e. truncate)), if you care about it.

Nice thanks for the tip. I'll give that a try.

This topic is closed to new replies.

Advertisement