Min*_*ICT 0 x86 operating-system kernel nasm x86-16
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
Run Code Online (Sandbox Code Playgroud)
我希望程序等待 1 秒然后继续关闭。目前,它在关闭消息后立即关闭。我在 nasm 制作的自定义操作系统上运行它。
假设您的程序由 ROM-BIOS(不是 EFI)加载,并且您在(真实/虚拟)86 模式下运行,并且您启用了中断 ( sti),并且您没有重新配置 PIC 和 PIT,并且也没有更改中断 8(默认 IRQ 0)处理程序,然后您可以使用 0_046Ch(相当于 40h:6Ch)处的双字,该双字保存自午夜以来的计时器滴答声,并且每秒递增约 18.2 次(约 18.2 Hz)由 ROM-BIOS 的中断 8 处理程序处理。
在我的程序中,我通常只检查计数器的较低字更改的频率,这通常足够准确,并且不需要任何特殊的午夜翻转处理。
(简单的方法是获取当前的滴答数并添加您想要等待的滴答数,然后在循环时检查滴答双字是否高于或等于计算值。但是,这需要午夜翻转处理才能正确工作所有情况。)
这是我的项目中一些计时器处理的源代码部分: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
Run Code Online (Sandbox Code Playgroud)
这是该计时器的设置:
xor ax, ax
mov word [getline_timer_count], ax
mov word [getline_timer_last], ax
mov word [getline_timer_func], .timer
call getline00
Run Code Online (Sandbox Code Playgroud)
word [getline_timer_func]如果输入是从串行端口完成的(每当我们使用此计时器时都会出现这种情况),则getline00 在等待输入时会重复调用函数指针。这是在https://hg.ulukai.org/ecm/ldebug/file/82570f7094b8/source/lineio.asm#l814:
call near word [getline_timer_func]
Run Code Online (Sandbox Code Playgroud)
下面的行通过指向一个空函数(这只是一个retn)来禁用计时器:
mov word [getline_timer_func], dmycmd
Run Code Online (Sandbox Code Playgroud)
将它们放在一起,这是您的睡眠处理程序:
%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:
Run Code Online (Sandbox Code Playgroud)
我的程序源代码的更改:
cx和中dx。.loop本地标签。这也意味着我们不必使用push和保留寄存器内容pop。hlt使得机器可以空转。