powerCommand:
mov si, powerOFF
call printString
;sleep command here
mov ax, 0x1000
mov ax, ss
mov sp, 0xf000
mov ax, 0x5307
mov bx, 0x0001
mov cx, 0x0003
int 0x15
ret
我希望程序等待1秒钟,然后继续关闭。此刻,它会在关闭消息后立即关闭。我正在用nasm定制的操作系统运行它。
答案 0 :(得分:4)
假设您的程序是通过ROM-BIOS(不是EFI)加载的,并且您正在(真实/虚拟)86模式下运行,并且启用了中断(sti
),而您没有重新配置PIC和PIT,并且也没有更改中断8(默认IRQ 0)处理程序,那么您可以使用0_046Ch(相当于40h:6Ch)处的dword,它自午夜以来一直保持计时器滴答,并在大约ROM-BIOS的中断8处理程序每秒显示18.2次(大约为18.2 Hz)。
在我的程序中,我通常只检查计数器低位字的更改频率,通常这足够准确,并且不需要任何特殊的午夜翻转处理。
(幼稚的方法是获取当前的滴答声计数并添加要等待的任意多个滴答声,然后在循环时检查tick dword是否高于或等于计算值。但是,这需要午夜翻转处理在任何情况下都能正常工作。)
这是我的项目https://hg.ulukai.org/ecm/ldebug/file/82570f7094b8/source/debug.asm#l1367
中某些计时器处理的源代码部分.timer:
push ax
push dx
push cx
push es
mov dx, 40h
mov es, dx
mov cx, word [getline_timer_count]
mov dx, word [getline_timer_last]
cmp dx, word [es:6Ch]
je .timer_next
mov dx, word [es:6Ch]
inc cx
mov al, 18
mul byte [serial_keep_timeout]
test ax, ax
jz .timer_next
cmp cx, ax
jb .timer_next
pop es
mov dx, msg.serial_no_keep_timer
jmp .no_keep
.timer_next:
mov word [getline_timer_count], cx
mov word [getline_timer_last], dx
pop es
pop cx
pop dx
pop ax
retn
这是该计时器的设置:
xor ax, ax
mov word [getline_timer_count], ax
mov word [getline_timer_last], ax
mov word [getline_timer_func], .timer
call getline00
getline00在等待输入的过程中反复调用word [getline_timer_func]
中的函数指针(如果输入是通过串行端口完成的(每次使用此计时器时都是这种情况))。那是https://hg.ulukai.org/ecm/ldebug/file/82570f7094b8/source/lineio.asm#l814:
call near word [getline_timer_func]
下面的行通过指向一个空函数(只是一个retn
)来禁用计时器:
mov word [getline_timer_func], dmycmd
将它们放在一起,这是您的睡眠处理程序:
%assign SLEEP_SECONDS 1
sleep:
xor cx, cx ; initialise counter to zero
xor dx, dx ; initialise "prior value" to zero
; (any value will do, at worst it is a match to the
; tick low word and we will wait one tick longer)
mov ax, 40h
mov es, ax ; => ROM-BIOS data area
.loop:
cmp word [es:6Ch], dx
; still same ?
je .next ; yes, just wait for next -->
mov dx, word [es:6Ch]
; update our last-seen low tick word value
inc cx ; increment our counter
cmp cx, SLEEP_SECONDS * 18
; as many ticks elapsed as we want ?
jae .end ; yes, end the loop -->
; (fall through to .next)
.next:
sti ; insure interrupts are enabled for the hlt
hlt ; idle the machine while waiting for IRQs
jmp .loop ; continue the loop -->
.end:
程序源代码中的更改:
cx
和dx
中。.loop
本地标签。这也意味着我们不必使用push
和pop
保留寄存器内容。hlt
使机器可以空闲。