如何在16位MASM Assembly x86中创建睡眠功能?

Yuv*_*rmi 10 windows assembly sleep

我试图在16位MASM Assembly x86中创建一个睡眠/延迟程序,比如说,每500毫秒在屏幕上打印一个字符.从我所做的研究来看,似乎有三种方法可以实现这一点 - 我想使用一个使用CPU时钟滴答的方法.

请注意我在Mac OS X Snow Leopard上通过VMWare Fusion运行Windows XP - 我不确定这是否会影响任何内容.

有人可以指出我正确的方向,或提供一个我可以调整的工作代码吗?谢谢!

我发现的代码应该每秒在屏幕上打印'A',但不起作用(我还是想用毫秒).

TOP:
MOV AH,2C
INT 21
MOV BH,DH  ; DH has current second
GETSEC:      ; Loops until the current second is not equal to the last, in BH
MOV AH,2C
INT 21
CMP BH,DH  ; Here is the comparison to exit the loop and print 'A'
JNE PRINTA
JMP GETSEC
PRINTA:
MOV AH,02
MOV DL,41
INT 21
JMP TOP
Run Code Online (Sandbox Code Playgroud)

编辑:按照GJ的建议,这是一个工作程序.打电话吧

DELAY PROC
 TIMER:
 MOV     AH, 00H
 INT     1AH
 CMP     DX,WAIT_TIME
 JB      TIMER
 ADD     DX,3         ;1-18, where smaller is faster and 18 is close to 1 second
 MOV     WAIT_TIME,DX
 RET
DELAY ENDP
Run Code Online (Sandbox Code Playgroud)

kqu*_*inn 11

这不能在纯MASM中完成.用于设置固定延迟的所有旧技巧都假设您完全控制机器并且是CPU上运行的唯一线程,因此如果您等待5亿个周期,500,000,000/f则将经过几秒钟(对于CPU来说)频率f); 对于1GHz处理器来说,它是500毫秒.

因为您在现代操作系统上运行,所以您与许多其他线程共享CPU(其中,内核 - 无论您做什么,都不能优先于内核!),所以只等待5亿个周期你的线程将意味着在现实世界中超过5亿个周期.仅用户空间代码无法解决此问题; 你需要内核的合作.

解决此问题的正确方法是查找Win32 API函数将挂起您的线程达到指定的毫秒数,然后只调用该函数.您应该可以直接从程序集中执行此操作,可能还有链接器的其他参数.或者,可能有一个NT内核系统调用来执行此功能(我对NT系统调用的经验很少,老实说不知道NT系统调用表是什么样的,但是睡眠功能是我可能会做的事情.期待看到).如果系统调用可用,则从程序集发出直接系统调用可能是执行所需操作的最快方法; 它也是最便携的(但是,你正在编写程序集!).

编辑:查看NT内核系统调用表,似乎没有任何与休眠相关的调用或获取日期和时间(就像您的原始代码使用的那样),但是有几个系统调用来设置和查询定时器.等待计时器达到所需延迟时旋转是一种有效的,如果不优雅的解决方案.


小智 5

使用INT 15h,功能86h:

呼叫:AH = 86h CX:DX =美国的间隔


GJ.*_*GJ. 3

实际上,您可以使用 ROM BIOS 中断 1Ah 功能 00h,“读取当前时钟计数”。或者您可以读取地址 $40:$6C 处的双字,但必须确保原子读取。它由 MS-DOS 以大约 18.2 Hz 的频率递增。

欲了解更多信息,请阅读:DOS 时钟

  • “DOS 时钟”链接将我带到一个空白页。 (3认同)