【问题标题】:Assembly system time DOS汇编系统时间 DOS
【发布时间】:2014-06-21 20:12:48
【问题描述】:

我写了一些代码:

petla:
mov ah,2
int 1ah

mov[sekunda], dh
mov ah, [sekunda]
mov cl, 4
and ah, 11110000b 
shr ah, cl  
mov dl, ah
add dl, '0'
mov ah, 2
int 21h

mov ah, [sekunda]
and ah, 00001111b   
mov dl, ah
add dl, '0'
mov ah, 2
int 21h

jmp petla

sekunda db 0

当我运行这个程序时,我会看到很多值(秒)如下所示:

12
12
12
12
12
13
13

如何修改代码只显示一次一值(一秒一值)?

如何修改代码以例如每 5 秒显示一次?

我需要在我的主代码中使用这个,在 x 秒后某些内容将被更改。

【问题讨论】:

    标签: assembly dos x86-16


    【解决方案1】:

    请记住,对于计算机而言,秒是非常很长的一段时间(嗯,至少在过去 40-50 年!)

    你的小程序获取时间值的速度非常快,所以每秒可以获取数千(甚至百万!)次当前时间。

    如果您只想要输出更改时的输出,请尝试以下操作:(我们正在添加比较)

    petla:
        mov ah,2
        int 1ah             ; get time
    
        mov ah, [sekunda]   ; retrieve last good value
        cmp ah, dh          ; is it same as last good value?
        jz  pet1a           ; yup, ignore it, loop again!
    
        mov [sekunda], dh   ; save seconds
    
        mov ah, [sekunda]   ; get seconds value
        mov cl, 4           ; ready to shift 4 bits
        and ah, 11110000b   ; isolate top nybble
        shr ah, cl          ; shift into low nybble
        mov dl, ah          ; move into proper register for output
        add dl, '0'         ; magically transform into ASCII digit
        mov ah, 2           ; Select 'write char'
        int 21h             ; uh... write char!
    
        mov ah, [sekunda]   ; hey, this seems familiar!
        and ah, 00001111b   ; isolate lower nybble!
        mov dl, ah          ; no, really.. deja vu!
        add dl, '0'         ; TaaDaa, it's a char!
        mov ah, 2           ; Select 'write char'
        int 21h             ; make it so!
    
        jmp petla           ; do it again!  (make this a 'ret', see below)
    

    现在这个小程序会每秒不断输出一个新的值……也许不是很有价值……

    但是等等!还有更多!

    如果您将 LAST 指令 (jmp pet1a) 更改为返回 (ret),我们可以将其用作“wait_for_five_seconds”例程的一部分...如下所示:

    wait_for_five_seconds:
        mov al,5              ; how many seconds to wait
    wait_for_al_seconds:      ; explained below
    wait_loop:
        push ax               ; save our counter (al)
        call pet1a            ; this will call pet1a, which will not return until it has displayed a new second value
        pop ax                ; retrieve our counter (pet1a changes value of ah/al/ax, remember?)
        dec al                ; decrease al by one (does not set flags!!)
        or al,al              ; set flags
        jnz wait_loop         ; al=0?  nope, around we go again!
        ret                   ; go back to whomever called us!
    

    现在,如果您想暂停 5 秒,只需拨打 wait_for_five_seconds 即可!

    如果您删除 pet1a 中将字符写出的部分……那么您会有一秒的 silent 延迟。用于暂停。

    如果您想暂停 17 秒怎么办?嗯,我们的延迟是基于进入wait_loop部分时al的值...那如果我们预加载al,然后调用等待位呢?

        mov al, 17                 ; delay for 17 seconds!
        call wait_for_al_seconds   ; delay for whatever number is in al
    

    但要小心,如果 al 的值为 0... 它必须一直循环... 0, -1, -2, ... -127, -128, 127, 126 ... 2, 1, 0 ... 你会暂停 256 秒! (4 分 16 秒!)。 (请参阅 Signed Number Representations 了解为什么它在 -128 左右变得奇怪)

    我希望这对您有所帮助,也许会给您一些想法。这不是一个“暂停”解决方案的想法,因为它不是一个确切的延迟,如果你在新的第二秒计时之前调用pet1a just,那么第一次点击的延迟会很小,然后剩下的时间是整秒......所以所需的 5 秒延迟可能在 4.000001 秒到 5 秒之间。但这是一个开始。

    【讨论】:

    • 我会第一个承认这不是最好的代码,也不是暂停或延迟的最佳方式。但考虑到 OP 的原始代码和平台,我认为我们正在学习并需要一些指导。就像我说的,希望你也能得到想法并尝试其他事情,编程很棒,而汇编编程更棒! (是的,我做了不少汇编编程,各种平台)
    • 我仍然遇到延迟问题我将最后一行 jmp petla 更改为 call wait_for_five_seconds 但仍然延迟 1 秒而不是 5 秒
    • 不...最后一行到ret,在其他地方,call wait_for_five_seconds。再读一遍。 :)
    猜你喜欢
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    • 2010-12-18
    • 2017-04-27
    • 1970-01-01
    • 2010-12-10
    • 1970-01-01
    相关资源
    最近更新 更多