我正在使用 nasm 在裸機 16 位實模式程式集上撰寫程式。我想休眠(暫停執行) x 毫秒,但是我還沒有找到一種方法來做到這一點。
編輯:這是我的代碼。我想在每個字符被輸入到螢屏之間添加大約 0.3 秒的延遲。
[bits 16] ; use 16 bits
[org 0x7c00] ; sets the start address
init:
mov si, msg ; loads the address of "msg" into SI register
mov ah, 0x0e ; sets AH to 0xe (function teletype)
print_char:
lodsb ; loads the current byte from SI into AL and increments the address in SI
cmp al, 0 ; compares AL to zero
je done ; if AL == 0, jump to "done"
int 0x10 ; print to screen using function 0xe of interrupt 0x10
jmp print_char ; repeat with next byte
done:
hlt ; stop execution
msg: db "The quick brown fox jumps over the lazy dog.", 0 ; we need to explicitely put the zero byte here
times 510-($-$$) db 0 ; fill the output file with zeroes until 510 bytes are full
dw 0xaa55 ; magic number that tells the BIOS this is bootable
uj5u.com熱心網友回復:
有一天,我也需要一個延遲例程,能夠實作從 0.5 秒到幾毫秒的延遲。在這個 CodeReview 問題中閱讀所有相關內容,尤其是我需要采用這種方法的原因。
我的解決方案是找出延遲例程在標準 18.2Hz 計時器的 2 個滴答聲之間的間隔內可以進行多少次迭代。這些滴答聲相隔 55 毫秒。因為有時測量值可能不穩定,所以我只接受連續 2 次測量值變化小于 1%% 的結果。最后,我將良好的測量結果除以 55 以獲得每毫秒的迭代次數,即 SpeedFactor。此后,每當我想暫停程式時,我都會將所需的延遲乘以以毫秒為單位表示的 SpeedFactor,然后在延遲例程中執行該次數的迭代。
完整代碼:
[bits 16]
[org 0x7C00]
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00
cld
; Measure the number of iterations (within the ShortWait routine) per msec
; Only accept if consecutive measurements vary by less than 1%%
; If measurements remain erratic than do accept the last one
mov bp, 10 ; Max try
call GetSpeedFactor ; -> DX:AX
.a: xchg si, ax ; 'mov si, ax'
mov di, dx
call GetSpeedFactor ; -> DX:AX
push ax dx ; (1)
.b: sub ax, si
sbb dx, di
jnb .c
add ax, si
adc dx, di
xchg si, ax
xchg di, dx
jmp .b
.c: mov cx, 1000
xchg ax, cx
mul dx
xchg ax, cx
mov dx, 1000
mul dx
add dx, cx
sub si, ax
sbb di, dx
pop dx ax ;(1)
cmc
dec bp
jnbe .a
mov [SpeedFactor], ax
mov [SpeedFactor 2], dx
mov si, msg
lodsb
More: mov bx, 0x0007 ; BH DisplayPage 0, BL GraphicsColor 7
mov ah, 0x0E ; BIOS.Teletype
int 10h
mov bx, 300 ; 0.3 sec
call Pause
lodsb
cmp al, 0
jne More
cli
hlt
jmps $-2
msg db "The quick brown fox jumps over the lazy dog.", 0
SpeedFactor dd 0
; ----------------------------------------------
; IN () OUT (dx:ax)
; Wait for the start of a new TimerTick period (54.9254 msec)
; Then measure a 4 tick period (219.7016 msec)
GetSpeedFactor: push bx cx
mov bx, 1
call .ShortWait ; -> DX:AX BX=0
mov bl, 4 ; BH=0
call .ShortWait ; -> DX:AX BX=0
mov cx, 10
xchg ax, cx
mul dx
xchg ax, cx
mov dx, 10
mul dx
add dx, cx
mov cx, 2197
xchg ax, bx ; BX=0
xchg dx, ax
div cx
xchg ax, bx
div cx
mov dx, bx
pop cx bx
ret
; - - - - - - - - - - - - - - - - - - - - - - -
.ShortWait: mov ax, -1
cwd
; --- --- --- --- --- --- --- ---
; IN (dx:ax,bx) OUT (dx:ax,bx)
; Do DX:AX iterations or loop until Timer did BX Ticks
ShortWait: push ds cx si di
xchg si, ax ; 'mov si, ax'
mov di, dx
xor ax, ax
cwd
mov ds, ax
.a: mov cx, [046Ch] ; BIOS Timer
.b: sub si, 1
sbb di, 0
jb .c
add ax, 1
adc dx, 0
cmp cx, [046Ch]
je .b
dec bx
jnz .a
.c: pop di si cx ds
ret
; ----------------------------------------------
; IN (bx) OUT ()
Pause: push ax bx dx
mov ax, [SpeedFactor 2]
mul bx
xchg bx, ax
mul word [SpeedFactor]
add dx, bx
mov bx, -1
call ShortWait ; -> DX:AX BX
pop dx bx ax
ret
; ----------------------------------------------
times 510-($-$$) db 0
dw 0xAA55
代碼用 FASM 匯編。對于 NASM,您需要更改代碼,例如
push ax bx dx
...
pop dx bx ax
進入
push ax
push bx
push dx
...
pop dx
pop bx
pop ax
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/315394.html
上一篇:列印時訪問超出字串邊界的記憶體
