📄 delay18.asm
字号:
; Delay18.asm
;
; Software/Hardware based Delay Subroutine
.xlist
include stdlib.a
includelib stdlib.lib
.list
; PPI_B is the I/O address of the keyboard/speaker control
; port. This program accesses it simply to introduce a
; large number of wait states on faster machines. Since the
; PPI (Programmable Peripheral Interface) chip runs at about
; the same speed on all PCs, accessing this chip slows most
; machines down to within a factor of two of the slower
; machines.
PPI_B equ 61h
; RTC is the address of the BIOS timer variable (40:6ch).
; The BIOS timer interrupt code increments this 32-bit
; location about every 55 ms (1/18.2 seconds). The code
; which initializes everything for the Delay routine
; reads this location to determine when 1/18th seconds
; have passed.
RTC textequ <es:[6ch]>
dseg segment para public 'data'
; TimedValue contains the number of iterations the delay
; loop must repeat in order to waste 1/18.2 seconds.
TimedValue word 0
; RTC2 is a dummy variable used by the Delay routine to
; simulate accessing a BIOS variable.
RTC2 word 0
dseg ends
;********************************************************
cseg segment para public 'code'
assume cs:cseg, ds:dseg
; Main program which tests out the DELAY subroutine.
Main proc
mov ax, dseg
mov ds, ax
print
byte "Delay test routine",cr,lf,0
; Okay, let's see how long it takes to count down 1/18th
; of a second. First, point ES as segment 40h in memory.
; The BIOS variables are all in segment 40h.
;
; This code begins by reading the memory timer variable
; and waiting until it changes. Once it changes we can
; begin timing until the next change occurs. That will
; give us 1/18.2 seconds. We cannot start timing right
; away because we might be in the middle of a 1/18.2
; second period.
mov ax, 40h
mov es, ax
mov ax, RTC
RTCMustChange: cmp ax, RTC
je RTCMustChange
; Okay, begin timing the number of iterations it takes
; for an 18th of a second to pass. Note that this
; code must be very similar to the code in the Delay
; routine.
mov cx, 0
mov si, RTC
mov dx, PPI_B
align 4
TimeRTC: mov bx, 50
align 4
DelayLp: ;in al, dx ;Slow to hardware speed.
dec bx
jne DelayLp
cmp si, RTC
loope TimeRTC
neg cx ;CX counted down!
mov TimedValue, cx ;Save away
mov ax, ds
mov es, ax
printf
byte "TimedValue = %d",cr,lf
byte "Press any key to continue",cr,lf
byte "This will begin a delay of five seconds",cr,lf,0
dword TimedValue
getc
mov cx, 180
DelayIt: call Delay18
loop DelayIt
Quit: ExitPgm ;DOS macro to quit program.
Main endp
; Delay- This routine delays for approximately 1/18th second.
; Presumably, the variable "TimedValue" in DS has been
; initialized with an appropriate count down value
; before calling this code.
Delay18 proc near
push ds
push es
push ax
push bx
push cx
push dx
push si
mov ax, dseg
mov es, ax
mov ds, ax
; The following code contains two loops. The inside
; nested loop repeats 10 times. The outside loop
; repeats the number of times determined to waste
; 1/18.2 seconds. This loop accesses the hardware
; port "PPI_B" in order to introduce many wait states
; on the faster processors. This helps even out the
; timings on very fast machines by slowing them down.
; Note that accessing PPI_B is only done to introduce
; these wait states, the data read is of no interest
; to this code.
mov cx, TimedValue
mov si, es:RTC2
mov dx, PPI_B
align 4
TimeRTC: mov bx, 50
align 4
DelayLp: ;in al, dx
dec bx
jne DelayLp
cmp si, es:RTC2
loope TimeRTC
pop si
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
ret
Delay18 endp
cseg ends
sseg segment para stack 'stack'
stk dw 1024 dup (0)
sseg ends
end Main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -