assembly 程序集8086 -不使用DOS中断获取时间

6psbrbz9  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(156)

我怎样才能在不使用DOS中断的情况下获得时间?

ubbxdtey

ubbxdtey1#

不使用中断从DOS获取时间
如果您不想使用DOS.GetSystemTime函数2Ch(int 21h),则始终存在BIOS.GetRealTimeClockTime函数02h(int 1Ah)。这两个函数都以CH格式返回小时,以CL格式返回分钟,以DH格式返回秒但是与返回整数的DOS不同,BIOS以BCD格式返回数字。

23:17:45     DOS     vs     BIOS
         --------------------------
         CH=23 (17h)    CH=35 (23h)
         CL=17 (11h)    CH=23 (17h)
         DH=45 (2Dh)    CH=69 (45h)

如果你不想使用上面提到的任何一个函数,那么一个足够接近的近似值来自于阅读BIOS。TimerTick保存在内存地址046Ch(dword)。由于简化的数学,一天的第一分钟(并且只有第一分钟)将花费大约70秒。如果你的程序不显示秒,用户甚至不会注意到这一点。

; -> CH is hours [0,23]
; -> CL is minutes [0,59]
; IN () OUT (cx)
GetTime:
  cli
  push ds
  push ax
  push dx
  xor  cx, cx                     ; 00:00
  mov  ds, cx
  mov  al, byte ptr [046Ch + 2]   ; [0,24]
  cmp  al, 24
  je   .OK
  mov  ch, al                     ; Hours [0,23]
  mov  ax, 60
  mul  word ptr [046Ch]
  mov  cl, dl                     ; Minutes [0,59]
.OK:
  pop  dx
  pop  ax
  pop  ds
  sti
  ret

为了验证,我编写了下一个程序,它在控制台上以hh:mm:ss格式显示当前时间:

ORG  256                    ; Creating a .COM program

  mov  bh, -1                 ; LastKnownSeconds
Main:
  call GetTime                ; -> CH CL DH DL=0
  cmp  dh, bh
  je   Main                   ; Seconds didn't change
  mov  bh, dh
  mov  bl, ':'
  mov  al, ch                 ; Hours
  call PrintTrio              ; -> (AX DX)
  mov  al, cl                 ; Minutes
  call PrintTrio              ; -> (AX DX)
  mov  bl, 13
  mov  al, bh                 ; Seconds
  call PrintTrio              ; -> (AX DX)
  mov  dl, 10
  mov  ah, 02h                ; DOS.PrintCharacter
  int  21h
  mov  ah, 01h                ; BIOS.CheckKeystroke
  int  16h                    ; -> AX ZF
  jz   Main                   ; No key waiting
  mov  ah, 00h                ; BIOS.GetKeystroke
  int  16h                    ; -> AX
  ret                         ; TerminateProgram
; ----------------------------
; IN (al,bl) OUT () MOD (ax,dx)
PrintTrio:
  aam                         ; -> AH = AL / 10, AL = AL % 10
  add  ax, '00'               ; Convert to ASCII
  push ax                     ; (1)
  mov  dl, ah
  mov  ah, 02h                ; DOS.PrintCharacter
  int  21h
  pop  dx                     ; (1)
  mov  ah, 02h                ; DOS.PrintCharacter
  int  21h
  mov  dl, bl
  mov  ah, 02h                ; DOS.PrintCharacter
  int  21h
  ret
; ----------------------------
; IN () OUT (ch,cl,dh,dl=0)
GetTime:
  push ds
  push ax
  push bx
  xor  dx, dx                 ; 00:00:00
  xor  cx, cx
  mov  ds, cx
  cli
  mov  ax, word ptr [046Ch]   ; BIOS.TimerTick
  mov  bx, word ptr [046Ch+2] ; [0,24]
  sti
  cmp  bl, 24
  je   .OK
  mov  ch, bl                 ; Hours [0,23]
  mov  bl, 60                 ; BH=0
  mul  bx
  mov  cl, dl                 ; Minutes [0,59]
  mul  bx
  mov  dh, dl                 ; Seconds [0,59]
  mov  dl, 0
.OK:
  pop  bx
  pop  ax
  pop  ds
  ret
; ----------------------------

相关问题