NumSound


Program description

The program plays sounds for each numeric key on extended keyboard when Num lock is on. Operators had problem with entering data when Num lock was off and they pressed arrows instead numbers and they asked to create this utility.

Program starts, checks previous copy in memory and finishes if it exists. Else it decodes following code in memory (protection from static and dynamic (Turbo Debugger) disassembling), moves resident part to PSP, sets up interruption's vector and finishes. Resident part responds on keyboard interruption and plays appropriate sound. Resident part can be disabled and enabled by pressing keys CTRL+SHIFT(L)+SHIFT(R).

Source Code
             title numsound.asm
             page 60,120
  code       segment byte public
             assume cs:code,ds:code,es:code
             org 100h
  beg        proc far
  start:     jmp init
  beg        endp
  ;secr       db 'Barbotko S. 1993'   ; copyright
  secr       db 30h,0a1h,98h,9ch,0eeh,8dh,0b6h,0f6h,02h,99h,0b8h,80h,62h,72h,0e4h,0cch
  inter2F:   pushf
             cmp ax,0ee00h   ; 
             jz itis_my
             cmp ax,0ef00h
             jnz no_my 
  itis_my:   mov al,0ffh
             popf
             iret         
  no_my:     popf
             db 0EAh                            ; jmp far using old vector 
  offt_2f    dw 0
  segt_2f    dw 0

  inter:     mov word ptr cs:ax_old+offs_psp,ax    ; save flags and registers 
             lahf
             mov byte ptr cs:f_old+offs_psp,ah 
             mov word ptr cs:es_old+offs_psp,es
             mov word ptr cs:di_old+offs_psp,di
             mov word ptr cs:cx_old+offs_psp,cx
             mov al,byte ptr cs:kod_old+offs_psp   ; is previous code E0h ?
             cmp al,0E0h
             jz  inter_old            ;if yes, this is key of extended keyboard,  
             mov ah,02h               ; don't work with it.
             int 16h                  ; get status of CTRL , SHIFT (R)(L)
;             mov ah,al                ; and NumLock  
 ;            and ah,00000111b ;(ctrl_shift)
  ;           cmp ah,00000111b ;(ctrl_shift)
             mov ah,byte ptr cs:run_off+offs_psp 
   		     test al,111b
             jnz cont                  ; if their combination then invert     
             not ah                    ; byte off/on 
             mov byte ptr cs:run_off+offs_psp,ah
  cont:      cmp ah,0
             jnz inter_old 
             test al,00100000b ;(numactiv) - check status of NumLock...
             cmp al,0     
             jnz  inter_old             ; if it is set then don't work with it 
  inter_new: 
             mov ax,cs                  ; get ... 
             mov es,ax
             mov di,offset ar_sc_kod+offs_psp
             cld
             mov cx,11
             in al,60h                   ; ... scan-code and search for 
 repne scasb                 ; frequency for it
             jne inter_old
             mov di,10
             sub di,cx
             sal di,1
             mov cx,word ptr es:ar_hz+offs_psp[di]  ; get counter ...             
  soun:      mov al,0b6h                            ; set up it (frequency)
             out 43h,al
             mov al,cl 
             out 42h,al
             mov al,ch 
             out 42h,al
             in  al,61h                   ; turn on ... 
             or  al,00000011b ;(sound_on)
             out 61h,al
             mov cx,2500h                 ;... delay ...
  lp:        loop lp
             in  al,61h                   ; ... turn off
             and al,11111100b ;(sound_off)
             out 61h,al
  inter_old: in al,60h                    ; remember scan-code for next time
             mov byte ptr cs:kod_old+offs_psp,al
             mov es,word ptr cs:es_old+offs_psp ; restore registies ...
             jmp dal
             nop
  ;copyr      db 'BarSSoft, 1993'                ; label for RELEASE
  copyr      db 30h,0a1h,94h,0dch,6dh,0eah,67h,46h,61h,01h,0c4h,0e4h,72h,66h 
  dal:
             mov di,word ptr cs:di_old+offs_psp
             mov cx,word ptr cs:cx_old+offs_psp
             mov ah,byte ptr cs:f_old+offs_psp
             sahf                               ; ... and flags
             mov ax,word ptr cs:ax_old+offs_psp 
             db 0EAh                            ; jmp far using old vector
  offt       dw 0
  segt       dw 0
  ; scan-codes of numeric keys 
  ar_sc_kod  db 4fh,50h,51h,4bh,4ch,4dh,47h,48h,49h,52h,53h  
  ; counters for them
  ar_hz      dw 2280,2152,1998,1912,1810,1708,1612,1522,1437,1356,1280
  f_old      db 0
  es_old     dw 0
  di_old     dw 0
  cx_old     dw 0
  ax_old     dw 0
  kod_old    db 0                    ; for previous scan-code
  run_off    db 0                    ; byte of program status - off/on  
  ctrl_shift equ 00000111b           ; combination of CTRL+SHIFT(R)+SHIFT(L) 
  numactiv   equ 00100000b           ; NumLock is set up
  sound_on   equ 00000011b           ; turning on ...
  sound_off  equ 11111100b           ; ... and turning off sound 
  beg_psp    equ 5ch                 ; beginning of resident part in PSP
  offs_psp   equ beg_psp-113h        ; offset for bytes of data 
  len_res    equ init-inter2F        ; length of resident part
  init:  
             mov ax,beg_psp
             mov bx,ax
             add ax,1c6h
             push ax 
             mov ax,cs
             mov ds,ax
             mov cl,3
             sar bx,cl
             sal bx,1             
             call step2
  lipa       db 58h,25h              ; pop ax  and ax,... , i.e. trash 

             mov di,offset secro     ; decode copyrights
             mov cx,0007h
             mov bx,offset copyr
             mov si,offset secr
  lp1:       mov ax,word ptr ds:[bx]
  lipa2      db 0ebh,0c8h            ; here will be: ror ax,cl
             mov word ptr ds:[bx],ax
             mov ax,word ptr ds:[si]
             ror ax,cl
             mov word ptr ds:[di],ax
             inc si
             inc si
             inc di
             inc di
             inc bx
             inc bx
             loop lp1 

             mov ax,word ptr es:[si]       ; still decoding
             ror ax,1
             ror ax,1
             mov word ptr es:[di],ax
             
             mov ah,9                ;copyright
             mov dx,offset soft
             int 21h

             mov ax,0ee00h
             int 2fh
             cmp al,0ffh    ; no - see result of int 2fh (0ee00h)
             jz no_run      ; yes - already in memory !
             mov ax,0ef00h
             int 2fh
             cmp al,0ffh    ; no - see result of int 2fh (0ef00h)
             jnz cont1      ; yes - already in memory !

  no_run:    mov ah,9                ; message 'already in memory' and end
             mov dx,offset in_mem
             int 21h
             int 20h       

  cont1:     mov ax,3509h            ; save vector 09h
             int 21h
             mov offt,bx
             mov segt,es

             mov ax,352fh            ; save vector 2fh
             int 21h
             mov offt_2f,bx
             mov segt_2f,es
             
             mov ax,cs               ; transfer resident part into PSP
             mov ds,ax               ; offset = 5Ch 
             mov es,ax
             mov di,beg_psp             
             mov si,offset inter2F
             mov cx,len_res
             cld
             rep movsb 
               
             mov dx,beg_psp+15h      ; set up new vector for 09h ...
             mov ax,2509h
             int 21h
             mov dx,beg_psp          ; ... and 2fh ...
             mov ax,252Fh
             int 21h

             mov ax,cs:[2ch]         ; release environment part
             mov es,ax               ; for other programs
             mov ah,49h
             int 21h

             mov dx,beg_psp+len_res  ; stay as resident noticing the new length
             int 27h

  step2:     
             mov ax,word ptr es:[bx] ; it it working under debugger ?
             mov es,ax
             cmp ax,word ptr es:[bx]
             je no_debug
             ret
             
  no_debug:  pop ax                  ; return skipping two bytes
             add bx,beg_psp+1beh
             mov byte ptr cs:[bx],0d3h 
             and ax,0fh
             cmp ax,0fh
             jz m1
             and ax,0f0h
  m1:        mov bx,ax
             ret

  soft       label byte              ; welcome message
             db 15 dup(32),201,42 dup(205),187,0dh,0ah
             db 15 dup(32),186,6 dup(32),'Sounds for numeric keys. v 2.4 (c)',6 dup(32) ,186,0dh,0ah
             db 15 dup(32),186,7 dup(32),'Copyright by '
  secro      db 'Barbotko S. 1993',7 dup(32),186,0dh,0ah
             db 15 dup(32),186,32,'For off/on press CTRL+SHIFT(L)+SHIFT(R)',32,186,0dh,0ah
             db 15 dup(32),200,42 dup(205),188,0dh,0ah,'$'
  in_mem     db 20 dup(32),"I'm already in memory !",'$'
  code       ends
             end start