NASM DOSBox 组件中的定时器实现

问题描述 投票:0回答:1

OP的文字:

我怎样才能在nasm汇编中制作一个向后计时器3分钟?

计时器不倒转。


编辑:

看起来

split mode
工作正常。不确定
lap mode

要制作倒计时器,我们可以编写类似于

changeTime
的程序。

但是我们应该使用

sub 55 ms
代替
add 55 ms
并调整其他计时器字段。


控制:

空格键 - 启动计时器/快照

左移 - 分割模式

右移 - 圈数模式

r - 重置计时器


代码:

[org 0x0100]

jmp start

;---------------------------------------;

hrs:        dw 0                        ; split mode data
min:        dw 0                        ;
s:          dw 0                        ;
ms:         dw 0                        ;

lhrs:       dw 0                        ; lap mode data
lmin:       dw 0                        ;
ls:         dw 0                        ;
lms:        dw 0                        ;

oldkb:      dd 0                        ; old vector

sMode:      db 0                        ; split mode
lMode:      db 0                        ; lap mode

startTimer: db 0                        ; timer on/off
snapshot:   db 0                        ; capture time
lapTime:    db 0                        ; lapTime on/off

location:   db 6                        ; display data starting from line 6

;---------------------------------------;

clrscr:
      pusha                             ;
      push es                           ;

      mov ax, 0xB800                    ; ax = B800
      mov es, ax                        ; es = B800
      xor di, di                        ; di = 0000
      mov ax, 0x720                     ; ax = 0720, ' ' + attrib 0x07
      mov cx, 2000                      ; cx = 2000

      cld                               ; clear DF, add di,2
      rep stosw                         ; es:di = ax

      pop es                            ;
      popa                              ;

      ret                               ;

;---------------------------------------;

printLayout:
      pusha                             ;
      push es                           ;

      mov ax, 0xB800                    ; ax = B800
      mov es, ax                        ; es = B800

      mov di, 160                       ; di = 0xAE

      mov byte[es:di+0], ' '            ; write to video mem
      mov byte[es:di+2], 'H'            ;
      mov byte[es:di+4], 'R'            ;
      mov byte[es:di+6], 'S'            ;

      mov byte[es:di+10], ':'           ;

      mov byte[es:di+14], 'M'           ;
      mov byte[es:di+16], 'I'           ;
      mov byte[es:di+18], 'N'           ;

      mov byte[es:di+22], ':'           ;

      mov byte[es:di+26], 'S'           ;
      mov byte[es:di+28], 'E'           ;
      mov byte[es:di+30], 'C'           ;

      mov byte[es:di+34], ':'           ;

      mov byte[es:di+38], 'M'           ;
      mov byte[es:di+40], 'L'           ;
      mov byte[es:di+42], 'S'           ;

      pop es                            ;
      popa                              ;

      ret                               ;

;---------------------------------------;

kbisr:                                  ; new keyboard interrupt, stay resident
      push ax                           ;

      in  al, 0x60                      ; read from port 0x60, output buffer

      cmp al, 147                       ; 'r' key, reset timer , 0x93 - 0x80 = 0x13
      jz  reset                         ; reset timer

      jnz modChanger                    ; change mode, split/lap

reset:
      mov word [cs:hrs], 0              ; reset split data
      mov word [cs:min], 0              ;
      mov word [cs:s], 0                ;
      mov word [cs:ms], 0               ;

      mov word [cs:lhrs], 0             ; reset lap data
      mov word [cs:lmin], 0             ;
      mov word [cs:ls], 0               ;
      mov word [cs:lms], 0              ;

      call clrscr                       ; clear screen

      mov byte [cs:location], 6         ; line 6, show split/lap time on this line if space bar is hit

      jmp EOI1                          ; end of interrupt 1

modChanger:                             ; switch between lap and split mode
      cmp al, 170                       ; left shift, 0xaa - 0x80 = 0x2a
      jnz checkLMode1                   ; activate lap mode
                                        ; activate split mode
      mov byte [cs:lMode], 0            ; lap mode = 0, deactivate lap mode

      cmp byte [cs:sMode], 1            ; if split mode = 1, already active?
      jz EOI1                           ; end of interrupt 1

      mov byte [cs:sMode], 1            ; else activate split mode = 1
      jmp EOI1                          ;

checkLMode1:                            ; lap mode
      cmp al, 182                       ; right shift, 0xb6 - 0x80 = 0x36
      jnz startTime                     ; start timer

      mov byte [cs:sMode], 0            ; split mode = 0

      cmp byte [cs:lMode], 1            ; if lap mode = 1, already active?
      jz  EOI1                          ; end of interrupt 1

      mov byte [cs:lMode], 1            ; lap mode = 1
      jmp EOI1

;---------------------------------------;

startTime:
      cmp al, 185                       ; space bar, 0xB9 - 0x80 = 0x39
      jnz oldKbHandler                  ; no, use old keyboard procedure
                                        ; yes, start the timer
      cmp byte [cs:startTimer], 1       ; is the timer activated?
      jz  check0                        ; yes
                                        ; no
      mov byte [cs:startTimer], 1       ; turn the timer on

check0:
      cmp byte [cs:sMode], 1            ; if split mode = 1
      jnz check1                        ; no
                                        ; yes
      mov byte [cs:snapshot], 1         ; snapshot = 1, total time from start
      jmp EOI1                          ; end of interrupt 1

check1:
      cmp byte [cs:lMode], 1            ; if lap mode = 1
      jnz EOI1

      mov byte [cs:lapTime], 1          ; lapTime = 1,  each lap time
      jmp EOI1

EOI1:
      mov al, 0x20                      ; send the signal to the 8259A controller
      out 0x20,al                       ; end of the interrupt

      pop ax                            ;
      iret                              ;

oldKbHandler:
      pop ax                            ;
      jmp far [cs:oldkb]                ; old keyboard handler code

;---------------------------------------;
;---------------------------------------;

printstr:
      push bp                           ;
      mov bp, sp                        ;

      pusha                             ;
      push es                           ;

      mov ax, 0xb800                    ; ax = b800
      mov es, ax                        ; es = b800

      mov di, [bp+4]                    ; di = 482, video mem offset
      mov ax, [bp+6]                    ; ax = hrs

      mov bx, 10                        ; bx = 000a
      mov cx, 0                         ; cx = 0000

nextdigit:
      mov dx, 0                         ; dx = 0000
      div bx                            ; dx:ax = 0000:hrs
      add dl, 0x30                      ; ascii digit
      push dx                           ;
      inc cx                            ; cx = 0001
      cmp ax, 0                         ;
      jnz nextdigit                     ;

      cmp cx, 1                         ;
      jnz nextpos

      mov byte [es:di], '0'             ; print '0' at curret position
      add di, 2                         ; next position

nextpos:
      pop dx
      mov dh, 0x07                      ; color
      mov [es:di], dx                   ;
      add di, 2                         ;
      loop nextpos                      ;

      pop es                            ;
      popa                              ;
      pop bp                            ;

      ret 4                             ;

;---------------------------------------;

printTime:
      push bp                           ;
      mov bp, sp                        ;

      pusha                             ;
      push es                           ;

      mov ax, 0xB800                    ; ax = b800
      mov es, ax                        ; es = b800

      mov di, [bp+4]                    ; di = 490

      ; print hours

      push word [bp+6]                  ; [bp+6] = hrs
      add di, 2                         ; di = 492
      push di                           ;
      call printstr                     ;

      ; print colon

      add di, 8                         ; di = 500
      mov byte [es:di], ':'             ;

      ; print minutes

      push word [bp+8]                  ; [bp+8] = mins
      add di, 4                         ; di = 504
      push di                           ;
      call printstr                     ;

      ; print colon

      add di, 8                         ; di = 512
      mov byte [es:di], ':'             ;

      ; print seconds

      push word [bp+10]                 ; [bp+10] = secs
      add di, 4                         ; di = 516
      push di                           ;
      call printstr                     ;

      ; print colon
      add di, 8                         ; di = 524
      mov byte [es:di], ':'             ;

      ; print miliseconds

      push word [bp+12]                 ; [bp+12] = milisecs
      add di, 4                         ; di = 528
      push di                           ;
      call printstr                     ;

      pop es                            ;

      popa                              ;
      pop bp                            ;
      ret 10                            ;

;---------------------------------------;

stopWatch:
      pusha
      push es

      call printLayout                  ; print " HRS : MIN : SEC : MLS "
                                        ; print " COUNTDOWN TIMER"

      ; print starting data
      ; save on the stack

      push word [cs:ms]                 ; miliseconds
      push word [cs:s]                  ; seconds
      push word [cs:min]                ; minutes
      push word [cs:hrs]                ; hours

      push 480                          ; video mem offset, line 3
      call printTime                    ;

      cmp byte [cs:startTimer], 1       ;
      jnz dEOI                          ; end of interrupt

changeTime:
      add word [cs:ms], 55              ; add 55 miliseconds
      cmp word [cs:ms], 1000            ; if 1000 miliseconds
      jle modCheck                      ;

      mov word [cs:ms], 0               ; reset miliseconds
      inc word [cs:s]                   ; +1 second
      cmp word [cs:s], 60               ; if 60 seconds
      jnz modCheck                      ;

      mov word [cs:s], 0                ; reset seconds
      inc word [cs:min]                 ; +1 minute
      cmp word [cs:min], 60             ; if 60 minutes
      jnz modCheck                      ;

      mov word [cs:min], 0              ; reset minutes
      inc word[cs:hrs]                  ; +1 hour

      jmp modCheck                      ;

modCheck:
      cmp byte [cs:sMode], 1            ; split mode
      jz splitMode

      cmp byte [cs:lMode], 1            ; lap mode
      jz  lapMode

      jmp EOI

dEOI:
      jmp EOI

;---------------------------------------;
;---------------------------------------;

splitMode:
      cmp byte [cs:snapshot], 1         ; is snapshot on?
      jnz eEOI                          ;

      mov byte [cs:snapshot], 0         ; deactivate snapshot

      push word [cs:ms]                 ; save on the stack
      push word [cs:s]                  ;
      push word [cs:min]                ;
      push word [cs:hrs]                ;

      ; position calculation

      mov al, 80                        ; calculate new cursor position
      mul byte [cs:location]            ;
      shl ax, 1                         ;

      add byte [cs:location], 2         ; used in calculation of the new offset

      push ax                           ;
      call printTime                    ;

eEOI:
      jmp EOI

;eEOI:  jmp EOI
;---------------------------------------;
;---------------------------------------;

lapMode:  
      cmp byte [cs:lapTime], 1          ;
      jnz xEOI                          ;

      mov byte [cs:lapTime], 0          ;

      mov ax, [cs:ms]                   ;
      mov bx, [cs:s]                    ;
      mov cx, [cs:min]                  ;
      mov dx, [cs:hrs]                  ;

l1:
      sub ax, [cs:lms]                  ;
      cmp ax, 0                         ;
      jge l2                            ;

      add ax, 1000                      ;
      dec bx                            ;

l2:
      mov [cs:lms],ax                   ;

      sub bx, [cs:ls]                   ;
      cmp bx, 0                         ;
      jge l3                            ;

      add bx, 60                        ;
      dec cx                            ;

l3:
      mov [cs:ls],bx                    ;
      jmp l4                            ; 

xEOI:
      jmp EOI                           ;

l4:
      sub cx, [cs:lmin]                 ;
      cmp cx, 0                         ;
      jge l5                            ;

      add cx, 60                        ;
      dec dx                            ;

l5:
      mov [cs:lmin],cx                  ;

      sub dx, [cs:lhrs]                 ;
      mov [cs:lhrs],dx                  ;

      push word [cs:lms]                ;
      push word [cs:ls]                 ;
      push word [cs:lmin]               ;
      push word [cs:lhrs]               ;

      ;Position Calculation

      mov al, 80                        ;
      mul byte [cs:location]            ;
      shl ax, 1                         ;

      add byte [cs:location], 2         ;

      push ax                           ;
      call printTime                    ;

      jmp EOI                           ;

EOI:
      mov al, 0x20                      ;
      out 0x20, al                      ;

return:
      pop es                            ;
      popa                              ;
      iret                              ;

;---------------------------------------;

start:
      mov ax, 0                         ; ax = 0000
      mov es, ax                        ; es = 0000

      mov ax, [es:9*4]                  ; int 09h, keyboard int offset
      mov [oldkb],ax                    ; ds:[oldkb] = xxxx
      mov ax, [es:9*4+2]                ; int 09h, keyboard int segment
      mov [oldkb+2], ax                 ; ds:[oldkb+2] = xxxx

      call clrscr                       ; clear screen

      cli                               ; clear IF

      mov word [es:9*4], kbisr          ; new int 09h procedure, offset
      mov [es:9*4+2], cs                ; and segment

      ; no save ? old off:seg
      mov word [es:8*4], stopWatch      ; new int 08h (timer), offset
      mov [es:8*4+2], cs                ; and segment, executed every 55 ms, 18.2 times per sec

      sti                               ; set IF

      mov dx, start                     ; dx = allocate memory,size(in bytes) = start offset
                                        ; dx = number of 16 bytes paragraphs
      add dx, 16                        ; include PSP (256 bytes = 16 paragraphs x 16 bytes)
      mov cl, 4                         ;
      shr dx, cl                        ; dx = (total bytes / 16 bytes) = paragraphs number

      mov ax, 0x3100                    ; terminate and stay resident
      int 21h                           ; DOS int
assembly timer nasm x86-16 dosbox
1个回答
0
投票

我添加了 5 个变量,其中包含倒数计时器的当前状态。 OP 想要 3 分钟,所以就这样了。

chrs:       dw 0                        ; countdown timer data
cmin:       dw 3                        ;
csec:       dw 0                        ;
cms:        dw 0                        ;

cdt:        db 0                        ; countdown timer on/off

c 添加到键盘处理程序

kbisr
以开始/停止倒计时。如果工作完成倒计时会自动重置回原始值。

注:

我认为单圈时间代码无法正常工作。我没深究过。

代码:

[org 0x0100]

jmp start

;---------------------------------------;

hrs:        dw 0                        ; split mode data
min:        dw 0                        ;
s:          dw 0                        ;
ms:         dw 0                        ;

lhrs:       dw 0                        ; lap mode data
lmin:       dw 0                        ;
ls:         dw 0                        ;
lms:        dw 0                        ;

oldkb:      dd 0                        ; old vector

sMode:      db 0                        ; split mode
lMode:      db 0                        ; lap mode

startTimer: db 0                        ; timer on/off
snapshot:   db 0                        ; capture time
lapTime:    db 0                        ; lapTime on/off

location:   db 6                        ; display data starting from line 6

      ; *** countdown timer code
      ; hardcoded values
      ; add own procedure if you want
      ; to take data from a user

chrs:       dw 0                        ; countdown timer data
cmin:       dw 3                        ;
csec:       dw 0                        ;
cms:        dw 0                        ;

cdt:        db 0                        ; countdown timer on/off

;---------------------------------------;

clrscr:
      pusha                             ;
      push es                           ;

      mov ax, 0xB800                    ; ax = B800
      mov es, ax                        ; es = B800
      xor di, di                        ; di = 0000
      mov ax, 0x720                     ; ax = 0720, ' ' + attrib 0x07
      mov cx, 2000                      ; cx = 2000

      cld                               ; clear DF, add di,2
      rep stosw                         ; es:di = ax

      pop es                            ;
      popa                              ;

      ret                               ;

;---------------------------------------;

printLayout:
      pusha                             ;
      push es                           ;

      mov ax, 0xB800                    ; ax = B800
      mov es, ax                        ; es = B800

      mov di, 174                       ; di = 0xAE

      mov byte[es:di+0], ' '            ; write to video mem
      mov byte[es:di+2], 'H'            ;
      mov byte[es:di+4], 'R'            ;
      mov byte[es:di+6], 'S'            ;

      mov byte[es:di+10], ':'           ;

      mov byte[es:di+14], 'M'           ;
      mov byte[es:di+16], 'I'           ;
      mov byte[es:di+18], 'N'           ;

      mov byte[es:di+22], ':'           ;

      mov byte[es:di+26], 'S'           ;
      mov byte[es:di+28], 'E'           ;
      mov byte[es:di+30], 'C'           ;

      mov byte[es:di+34], ':'           ;

      mov byte[es:di+38], 'M'           ;
      mov byte[es:di+40], 'L'           ;
      mov byte[es:di+42], 'S'           ;

      ; *** countdown timer code

      mov di, 260                       ;
      mov byte[es:di], 'C'              ;
      mov byte[es:di+2], 'O'            ;
      mov byte[es:di+4], 'U'            ;
      mov byte[es:di+6], 'N'            ;
      mov byte[es:di+8], 'T'            ;
      mov byte[es:di+10], 'D'           ;
      mov byte[es:di+12], 'O'           ;
      mov byte[es:di+14], 'W'           ;
      mov byte[es:di+16], 'N'           ;
      mov byte[es:di+18], ' '           ;
      mov byte[es:di+20], 'T'           ;
      mov byte[es:di+22], 'I'           ;
      mov byte[es:di+24], 'M'           ;
      mov byte[es:di+26], 'E'           ;
      mov byte[es:di+28], 'R'           ;

      pop es                            ;
      popa                              ;

      ret                               ;

;---------------------------------------;

kbisr:                                  ; new keyboard interrupt, stay resident
      push ax                           ;

      in  al, 0x60                      ; read from port 0x60, output buffer

      cmp al, 147                       ; 'r' key, reset timer , 0x93 - 0x80 = 0x13
      jz  reset                         ; reset timer

      ; *** countdown timer code

      cmp al, 174                       ; 'c' key, reset countdown timer, 0xAE - 0x80 = 0x2E
      jz countdown

      jnz modChanger                    ; change mode, split/lap

      ; *** countdown timer code

countdown:

;      cmp byte [cs:cdt], 2             ; cdt already reached zero?
;      jz cdt_reset

      cmp byte[cs:cdt], 1               ; is cdt activated?
      jz cdt_stop

      inc byte[cs:cdt]                  ; start cdt
      jmp EOI1                          ; end of interrupt 1

cdt_stop:
      dec byte [cs:cdt]                 ; stop cdt
      jmp EOI1                          ;

;cdt_reset:
;      dec byte [cs:cdt]
;      jmp EOI1

reset:
      mov word [cs:hrs], 0              ;
      mov word [cs:min], 0              ;
      mov word [cs:s], 0                ;
      mov word [cs:ms], 0               ;

      ; reset the lap time

      mov word [cs:lhrs], 0             ;
      mov word [cs:lmin], 0             ;
      mov word [cs:ls], 0               ;
      mov word [cs:lms], 0              ;

      call clrscr                       ; clear screen

      mov byte [cs:location], 6         ; line 6 , show split/lap time on this line if spacebar is hit

      jmp EOI1                          ; end of interrupt 1

modChanger:                             ; switch between lap and split mode
      cmp al, 170                        ; left shift, 0xaa - 0x80 = 0x2a
      jnz checkLMode1                    ; activate lap mode
                                         ; activate split mode
      mov byte [cs:lMode], 0             ; lap mode = 0, deactivate lap mode

      cmp byte [cs:sMode], 1             ; if split mode = 1, already active?
      jz EOI1                            ; end of interrupt 1

      mov byte [cs:sMode], 1             ; else activate split mode = 1
      jmp EOI1                           ;

checkLMode1:                             ; lap mode
      cmp al, 182                        ; right shift, 0xb6 - 0x80 = 0x36
      jnz startTime                      ; start timer

      mov byte [cs:sMode], 0             ; split mode = 0

      cmp byte [cs:lMode], 1             ; if lap mode = 1, already active?
      jz  EOI1                           ; end of interrupt 1

      mov byte [cs:lMode], 1             ; lap mode = 1
      jmp EOI1

;----------------------------------------;

startTime:
      cmp al, 185                        ; space bar, 0xB9 - 0x80 = 0x39
      jnz oldKbHandler                   ; no, use old keyboard procedure
                                         ; yes, start the timer
      cmp byte [cs:startTimer], 1        ; is the timer activated?
      jz  check0                         ; yes
                                         ; no
      mov byte [cs:startTimer], 1        ; turn the timer on

check0:
      cmp byte [cs:sMode], 1             ; if split mode = 1
      jnz check1                         ; no
                                         ; yes
      mov byte [cs:snapshot], 1          ; snapshot = 1, total time from start
      jmp EOI1                           ; end of interrupt 1

check1:
      cmp byte [cs:lMode], 1             ; if lap mode = 1
      jnz EOI1

      mov byte [cs:lapTime], 1           ; lapTime = 1,  each lap time
      jmp EOI1

EOI1:
      mov al, 0x20                       ; send the signal to the 8259A controller
      out 0x20,al                        ; end of the interrupt

      pop ax                             ;
      iret                               ;

oldKbHandler:
      pop ax                             ;
      jmp far [cs:oldkb]                 ; old keyboard handler code

;---------------------------------------;
;---------------------------------------;

printstr:
      push bp                           ;
      mov bp, sp                        ;

      pusha                             ;
      push es                           ;

      mov ax, 0xb800                    ; ax = b800
      mov es, ax                        ; es = b800

      mov di, [bp+4]                    ; di = 482, video mem offset
      mov ax, [bp+6]                    ; ax = hrs

      mov bx, 10                        ; bx = 000a
      mov cx, 0                         ; cx = 0000

nextdigit:
      mov dx, 0                         ; dx = 0000
      div bx                            ; dx:ax = 0000:hrs
      add dl, 0x30                      ; ascii digit
      push dx                           ;
      inc cx                            ; cx = 0001
      cmp ax, 0                         ;
      jnz nextdigit                     ;

      cmp cx, 1                         ;
      jnz nextpos

      mov byte [es:di], '0'             ; print '0' at curret position
      add di, 2                         ; next position

nextpos:
      pop dx
      mov dh, 0x07                      ; color
      mov [es:di], dx                   ;
      add di, 2                         ;
      loop nextpos                      ;

      pop es                            ;
      popa                              ;
      pop bp                            ;

      ret 4                             ;

;---------------------------------------;

printTime:
      push bp                           ;
      mov bp, sp                        ;

      pusha                             ;
      push es                           ;

      mov ax, 0xB800                    ; ax = b800
      mov es, ax                        ; es = b800

      mov di, [bp+4]                    ; di = 490

      ; print hours

      push word [bp+6]                  ; [bp+6] = hrs
      add di, 2                         ; di = 492
      push di                           ;
      call printstr                     ;

      ; print colon

      add di, 8                         ; di = 500
      mov byte [es:di], ':'             ;

      ; print minutes

      push word [bp+8]                  ; [bp+8] = mins
      add di, 4                         ; di = 504
      push di                           ;
      call printstr                     ;

      ; print colon

      add di, 8                         ; di = 512
      mov byte [es:di], ':'             ;

      ; print seconds

      push word [bp+10]                 ; [bp+10] = secs
      add di, 4                         ; di = 516
      push di                           ;
      call printstr                     ;

      ; print colon
      add di, 8                         ; di = 524
      mov byte [es:di], ':'             ;

      ; print miliseconds

      push word [bp+12]                 ; [bp+12] = milisecs
      add di, 4                         ; di = 528
      push di                           ;
      call printstr                     ;

      pop es                            ;

      popa                              ;
      pop bp                            ;
      ret 10                            ;

;---------------------------------------;

stopWatch:
      pusha
      push es

      call printLayout                  ; print " HRS : MIN : SEC : MLS "
                                        ; print " COUNTDOWN TIMER"

      ; print starting data
      ; save on the stack

      push word [cs:ms]                 ; miliseconds
      push word [cs:s]                  ; seconds
      push word [cs:min]                ; minutes
      push word [cs:hrs]                ; hours

      push 494                          ; video mem offset, line 3
      call printTime                    ;

      ;cmp byte [cs:startTimer], 1
      ;jnz dEOI                         ; end of interrupt

      ;*** countdown timer code

      push word [cs:cms]                ; miliseconds
      push word [cs:csec]               ; seconds
      push word [cs:cmin]               ; minutes
      push word [cs:chrs]               ; hours

      push 578                          ; video mem offset, line 3
      call printTime                    ;

      cmp byte [cs:startTimer], 1       ; is the timer activated?
      jnz dEOI                          ; no, end of interrupt

cdtimer:
      pusha

      cmp byte [cs:cdt], 1              ; is cdt active?
      jnz cdt_deactivated               ;

      mov ax, [cs:cms]                  ;
      mov bx, [cs:csec]                 ;
      mov cx, [cs:cmin]                 ;
      mov dx, [cs:chrs]                 ;

      sub ax, 55                        ;
      cmp ax, 0                         ;
      jge cdt_secs                      ; if ms = [0 - 999]
                                        ; < 0, dec secs, adjust ms
      xor si,si                         ; check if cdt reached zero
      add si,dx                         ;
      add si,cx                         ;
      add si,bx                         ;

      cmp si,0                          ;
      jz cdt_zero                        ; countdown finished

      add ax, 1000                       ; adjust ms
      sub bx, 1                          ; dec secs

cdt_secs:
      mov [cs:cms], ax                   ; ms after calculation

      cmp bx, 0
      jge cdt_mins                       ; if sec = [0 - 59]
                                         ; < 0, dec mins, adjust secs
      add bx, 60                         ;
      sub cx, 1                          ;

cdt_mins:
      mov [cs:csec], bx                   ; secs after calculation

      cmp cx, 0                          ;
      jge cdt_hrs                        ; if mins = [0 - 59]
                                         ; < 0, dec hrs, adjust mins
      add cx, 60                         ;
      sub dx, 1                          ;

cdt_hrs:
      mov [cs:cmin], cx                  ; mins after calculations

      cmp dx, 0                          ;
      jge cdt_done                       ; if hrs = [0 - 23]
                                         ; < 0, adjust hrs
      add dx, 24                         ; x

cdt_done:
      mov [cs:hrs], dx                   ; hrs after calculation
      jmp cdt_deactivated

cdt_zero:
      mov byte [cs:cms], 0               ;
      mov byte [cs:cdt], 0               ; stop cdt
      mov byte [cs:cmin], 3              ; restart cdt

cdt_deactivated:
      popa

;----------------------------------------;

changeTime:
      add word [cs:ms], 55               ; add 55 miliseconds
      cmp word [cs:ms], 1000             ; if 1000 miliseconds
      jle modCheck                       ;

      mov word [cs:ms], 0                ; reset miliseconds
      inc word [cs:s]                    ; +1 second
      cmp word [cs:s], 60                ; if 60 seconds
      jnz modCheck                       ;

      mov word [cs:s], 0                 ; reset seconds
      inc word [cs:min]                  ; +1 minute
      cmp word [cs:min], 60              ; if 60 minutes
      jnz modCheck                       ;

      mov word [cs:min], 0               ; reset minutes
      inc word[cs:hrs]                   ; +1 hour

      jmp modCheck                       ;

modCheck:
      cmp byte [cs:sMode], 1             ; split mode
      jz splitMode

      cmp byte [cs:lMode], 1             ; lap mode
      jz  lapMode

      jmp EOI

dEOI:
      jmp EOI

;----------------------------------------;
;----------------------------------------;

splitMode:
      cmp byte [cs:snapshot], 1          ; is snapshot on?
      jnz eEOI                           ;

      mov byte [cs:snapshot], 0          ; deactivate snapshot

      push word [cs:ms]                  ; save on the stack
      push word [cs:s]                   ;
      push word [cs:min]                 ;
      push word [cs:hrs]                 ;

      ; position calculation

      mov al, 80                         ; calculate new cursor position
      mul byte [cs:location]             ;
      shl ax, 1                          ;
      add ax, 4                          ;

      mov si,0xb800                      ;
      mov es,si                          ;

      mov si, ax                         ; split mode id location
      mov byte [es:si], 'S'              ; split mode id
      add ax,10                          ;

      add byte [cs:location], 2          ; new line number

      push ax                            ;
      call printTime                     ;

eEOI:
      jmp EOI

;eEOI:  jmp EOI
;---------------------------------------;
;---------------------------------------;

lapMode:
      cmp byte [cs:lapTime], 1          ; is lap time activated?
      jnz xEOI                          ; no, end of interrupt
                                        ; yes
      mov byte [cs:lapTime], 0          ; deactivate lap time

      mov ax, [cs:ms]                   ; move current values to regs
      mov bx, [cs:s]                    ;
      mov cx, [cs:min]                  ;
      mov dx, [cs:hrs]                  ;
                                        ; Test:
                                        ; 03:04:04:500 - lap 1 - same as split mode
                                        ; 06:13:00:200 - lap 2 - 03:09:55:700
                                        ;
l1:
      sub ax, [cs:lms]                  ; 500-0=500 | 200-500=-300
      cmp ax, 0                         ;
      jge l2

      add ax, 1000                      ;           | -300+1000=700 |
      dec bx                            ;           | 0-1=-1 |
      cmp bx,0                          ;
      jb secs_59                        ;

secs_59:
      mov bx,59                         ; seconds, top of the range [0-59]

l2:
      mov [cs:lms],ax                   ; 500   | 700

      sub bx, [cs:ls]                   ; 4-0=4 | 59-4=55 |
      cmp bx, 0                         ;
      jge l3                            ;

      add bx, 60                        ;
      dec cx                            ;
      cmp cx,0                          ;
      jb mins_59                        ;

mins_59:
      mov cx,59                         ;

l3:
      mov [cs:ls],bx                    ; 4 | 55 |
      jmp l4

xEOI:
      jmp EOI

l4:
      sub cx, [cs:lmin]                 ; 4-0=4 | 13-4=9 |
      cmp cx, 0                         ;
      jge l5

      add cx, 60
      dec dx
      cmp dx,0
      jb hours_59

hours_59:
      mov dx,59                         ; hours, top of the range [0-59]
l5:
      mov [cs:lmin],cx                  ; 4 | 9 |

      sub dx, [cs:lhrs]                 ; 3-0=3 | 6-3=3|
      mov [cs:lhrs],dx                  ; 3 | 3 |

      push word [cs:lms]                ; value after each lap
      push word [cs:ls]
      push word [cs:lmin]
      push word [cs:lhrs]

      ; position calculation

      mov al, 80                        ; calculate new cursor position
      mul byte [cs:location]            ;
      shl ax, 1                         ;
      add ax, 4                         ;

      mov si,0xb800                     ;
      mov es,si                         ;

      mov si, ax                        ; lap mode id location
      mov byte [es:si], 'L'             ; lap mode id
      add ax,10                         ;

      add byte [cs:location], 2         ; new line number

      push ax                           ;
      call printTime                    ;

      jmp EOI

EOI:                                    ; EOI - End of Interrupt
      mov al, 0x20                      ;
      out 0x20, al                      ;

return:
      pop es                            ;
      popa                              ;

      iret                              ;

;---------------------------------------;

start:
      mov ax, 0                         ; ax = 0000
      mov es, ax                        ; es = 0000

      mov ax, [es:9*4]                  ; int 09h, keyboard int offset
      mov [oldkb],ax                    ; ds:[oldkb] = xxxx
      mov ax, [es:9*4+2]                ; int 09h, keyboard int segment
      mov [oldkb+2], ax                 ; ds:[oldkb+2] = xxxx

      call clrscr                       ; clear screen

      cli                               ; clear IF

      mov word [es:9*4], kbisr          ; new int 09h procedure, offset
      mov [es:9*4+2], cs                ; and segment

      ; no save ? old off:seg
      mov word [es:8*4], stopWatch      ; new int 08h (timer), offset
      mov [es:8*4+2], cs                ; and segment, executed every 55 ms, 18.2 times per sec

      sti                               ; set IF

      mov dx, start                     ; dx = allocate memory,size(in bytes) = start offset
                                        ; dx = number of 16 bytes paragraphs
      add dx, 16                        ; include PSP (256 bytes = 16 paragraphs x 16 bytes)
      mov cl, 4                         ;
      shr dx, cl                        ; dx = (total bytes / 16 bytes) = paragraphs number

      mov ax, 0x3100                    ; terminate and stay resident
      int 21h                           ; DOS int
© www.soinside.com 2019 - 2024. All rights reserved.