我怎样才能让操作系统在关机前等待一秒钟(nasm) [英] How can i make the os wait a second before shutdown ( nasm )

查看:19
本文介绍了我怎样才能让操作系统在关机前等待一秒钟(nasm)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 制作的自定义操作系统上运行它.

I want the program wait for 1 second then continue with shutdown. At the moment it shuts down instantly after the shutdown message. I am running it on my custom os made in nasm.

推荐答案

假设你的程序是由 ROM-BIOS (不是 EFI) 加载的,并且你在 (Real/Virtual) 86 模式下运行,并且你有中断启用 (sti),并且您没有重新配置 PIC 和 PIT,也没有更改中断 8(默认 IRQ 0)处理程序,那么您可以使用 0_046Ch 处的 dword(相当于, 40h:6Ch),它保持从午夜开始的计时器滴答声,并由 ROM-BIOS 的中断 8 处理程序每​​秒增加大约 18.2 次(大约 18.2 Hz).

Assuming your program is loaded by the ROM-BIOS (not EFI), and you're running in (Real/Virtual) 86 Mode, and you have interrupts enabled (sti), and you didn't reconfigure the PIC and the PIT, and also didn't change the interrupt 8 (default IRQ 0) handler, then you can use the dword at 0_046Ch (equivalently, 40h:6Ch) which holds the timer ticks since midnight, and is incremented circa 18.2 times per second (at circa 18.2 Hz) by the ROM-BIOS's interrupt 8 handler.

在我的程序中,我通常只检查计数器低位字的变化频率,这通常足够准确,并且不需要任何特殊的午夜翻转处理.

In my programs I generally just check for how often the lower word of the counter changes, which will usually be accurate enough, and doesn't need any special midnight rollover handling.

(天真的方法是获取当前滴答计数并添加您想要等待的任何滴答,然后在循环时检查滴答 dword 是否高于或等于计算值.但是,这需要午夜翻转处理以在所有情况下都能正常工作.)

(The naive approach is to take the current tick count and add however many ticks you want to wait, then when looping check whether the tick dword is above-or-equal the calculated value. However, this requires midnight rollover handling to correctly work in all circumstances.)

这是我的项目中一些计时器处理的源代码:https://hg.ulukai.org/ecm/ldebug/file/82570f7094b8/source/debug.asm#l1367

Here's the source part for some timer handling in a project of mine: 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 :

getline00 repeatedly calls the function pointer in word [getline_timer_func] while waiting for input, if input is done from the serial port (which is the case whenever we use this timer). That's at https://hg.ulukai.org/ecm/ldebug/file/82570f7094b8/source/lineio.asm#l814 :

    call near word [getline_timer_func]

以下行通过指向一个空函数(这只是一个retn)来禁用计时器:

And the following line disables the timer by pointing at an empty function (that's just a single retn):

    mov word [getline_timer_func], dmycmd

<小时>

总而言之,这是您的睡眠处理程序:


Putting it all together, here's your sleep handler:


%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:

我的程序源代码的更改:

Changes from my program's source:

  • sleep 滴答超时是在组装时根据预处理器定义的秒数计算的,而不是在运行时使用变量.
  • 计数器和上次看到的值在迭代之间不存储在变量中,而是始终保存在 cxdx 中.
  • 不使用函数指针框架,因为指针在睡眠处理期间将是一个常量.
  • 我们不会从计时器函数返回直到它再次被调用,而是跳回到 .loop 本地标签.这也意味着我们不必使用 pushpop 保留寄存器内容.
  • 我们没有检查按键(在我的程序中最终也会使机器闲置),我们只是在这里处于一个紧密的循环中.hlt 使机器可以空闲.
  • The sleep tick timeout is calculated at assembling time from a preprocessor define for the seconds, instead of using a variable at run time.
  • The counter and last seen value are not stored in variables between the iterations, rather they are always kept in cx and dx.
  • The function pointer framing is not used, as the pointer would be a constant during the sleep handling.
  • Instead of returning from the timer function until it is called again, we just jump back to the .loop local label. This also means we do not have to preserve the register contents with push and pop.
  • Instead of checking for a keypress (which in my program eventually idles the machine too), we just sit in a tight loop here. The hlt makes it so that the machine can idle.

这篇关于我怎样才能让操作系统在关机前等待一秒钟(nasm)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆