This cannot be done in pure MASM. All the old tricks for setting a fixed delay operate on the assumption that you have total control of the machine and are the only thread running on a CPU, so that if you wait 500 million cycles, exactly 500,000,000/f
seconds will have elapsed (for a CPU at frequency f
); that'd be 500ms for a 1GHz processor.
Because you are running on a modern operating system, you are sharing the CPU with many other threads (among them, the kernel -- no matter what you do, you cannot take priority over the kernel!), so waiting 500 million cycles in only your thread will mean that more than 500 million cycles elapse in the real world. This problem cannot be solved by userspace code alone; you are going to need the cooperation of the kernel.
The proper way to solve this is to look up what Win32 API function will suspend your thread for a specified number of milliseconds, then just call that function. You should be able to do this directly from assembly, possibly with additional arguments to your linker. Or, there might be an NT kernel system call to perform this function (I have very little experience with NT system calls, and honestly have no idea what the NT system call table looks like, but a sleep function is the sort of thing I might expect to see). If a system call is available, then issuing a direct system call from assembly is probably the quickest way to do what you want; it's also the least portable (but then, you're writing assembly!).
Edit: Looking at the NT kernel system call table, there don't appear to be any calls related to sleeping or getting the date and time (like your original code uses), but there are several system calls to set up and query timers. Spinning while you wait for a timer to reach the desired delay is one effective, if inelegant, solution.