home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sampler0 / critter.asm < prev    next >
Assembly Source File  |  1987-11-14  |  16KB  |  606 lines

  1.     PAGE    60,132
  2.     TITLE    CRITTER - Critical error handler
  3.  
  4. ;    (C) Copyright 1987 Forest Hill Software, Inc.
  5. ;            All rights reserved
  6. ;
  7. ;  Note: This program was put together with code from a handler that
  8. ;     was integrated with a larger project. Do not be supprised to
  9. ;     find added references and code which do not seem pertinent.
  10. ;     (it was also ported from Manx Assembler source code)
  11.  
  12.      DOSSEG
  13.     .MODEL    small
  14.     
  15.     .STACK    100h
  16.  
  17. LINE    equ    3            ;Starting line # of error window
  18. COLUMN    equ    9            ;Starting column of error window
  19. LINES    equ    4            ;# of lines in error window
  20. COLUMNS    equ    25            ;# of columns in error window
  21. DISK_ER    equ    80h            ;Disk error flag bit
  22. ALERT_D    equ    10            ;Alert tone duration
  23. ALERT_F    equ    300            ;Alert tone frequency
  24. NOCURS    equ    2000h            ;Scan lines setting for no cursor
  25.  
  26. ;    Allowed action bits - provided in ah when entering INT 24
  27.  
  28. QUI_BIT    equ    08h            ;Quit (fail) allowed bit
  29. RET_BIT    equ    10h            ;Retry allowed bit
  30. IGN_BIT    equ    20h            ;Ignore allowed bit
  31.  
  32. ;    Action key scan codes
  33.  
  34. SCAN_R    equ    19            ;Key 'R' pressed
  35. SCAN_I    equ    23            ;Key 'I' pressed
  36.  
  37. ;    Actions which can be supplied back to DOS in al
  38.  
  39. IGNORE    equ    0            ;Ignore the error
  40. RETRY    equ    1            ;Retry the operation
  41. ABORT    equ    2            ;Abort the program
  42. FAIL    equ    3            ;Fail the call
  43.  
  44. ;    Video attributes
  45.  
  46. CO_NORM    equ    17h    ;Color text attributes - normal   = white on blue
  47. CO_HIGH    equ    1eh    ;                        highlite = yellow on blue
  48. CO_ERRO    equ    9ch    ;                        error    = flash red on blue
  49. BW_NORM    equ    07h    ;B/W text attributes   - normal   = low intensity
  50. BW_HIGH    equ    0fh    ;                        highlite = high intensity
  51. BW_ERRO    equ    8fh    ;                        error    = flash high intens
  52. MO_NORM    equ    07h    ;Mono text attributes  - normal   = normal
  53. MO_HIGH    equ    70h    ;                        highlite = reverse
  54. MO_ERRO    equ    87h    ;                        error    = flash reverse
  55.  
  56. ;    Interupts
  57.  
  58. VIDEO    equ    10h        ;BIOS video services interupt
  59.     SETSIZE    equ    01h        ;Set cursor size
  60.     SETPOS    equ    02h        ;Set cursor position
  61.     READCUR    equ    03h        ;Read cursor
  62.     READCHR    equ    08h        ;Read character and attribute
  63.     WRITCHR    equ    09h        ;Write character and attribute
  64.     GETMODE    equ    0fh        ;Get video mode
  65. KEYBRD    equ    16h        ;BIOS keyboard services interupt
  66.     READKBD    equ    00h        ;Read keypress
  67.     TESTKBD    equ    01h        ;Test if keypress waiting
  68. DOS    equ    21h        ;DOS function call interrupt
  69.     DISPSTR equ    09h        ;Display $ terminated string
  70.     SETVECT    equ    2500h        ;Set interrupt vector
  71.     KEEPPGM    equ    3100h        ;Keep process (TSR)
  72.     GETVECT    equ    3500h        ;Get interrupt vector
  73.     EXITPGM    equ    4C00h        ;End process
  74. TICK    equ    08h        ;Clock tick interrupt
  75. CRITIC    equ    24h        ;Critical error handler interrupt
  76.  
  77.     .DATA
  78.  
  79. logon    db    13,10,'CRITTER - Your hyperactive critical error handler'
  80.     db    13,10,' (C) Copyright 1987 by Forest Hill Software, Inc.'
  81.     db    13,10,'$'
  82.  
  83.     .CODE
  84.  
  85. ;    Data to be kept in Code segment
  86.  
  87.     EVEN
  88.     
  89. top_stk    dw    0            ;Top of local stack
  90. old_cur    dw    0            ;Original cursor scan lines
  91. old_pos    dw    0            ;Original cursor position
  92. err_sta    dw    0            ;Error status information
  93. err_num    dw    0            ;Error number (code)
  94. tic_off dw    0            ;Saved INT 8 vector
  95. tic_seg    dw    0
  96. crt_off    dw    0            ;Saved INT 24 vector
  97. crt_seg    dw    0
  98. our_sp    dw    0            ;Our local stack
  99. our_ss    dw    0
  100. sav_sp    dw    0            ;Callers stack
  101. sav_ss    dw    0
  102. scr_sav    db    LINES*COLUMNS*2 dup (0)    ;Storage for used screen area
  103. scr_pag    db    0            ;Current screen page
  104. lin_sav    db    0            ;Temporary line # storage
  105. col_sav    db    0            ;Temporary column # storage
  106. line_c    db    0            ;Line counter
  107. colum_c    db    0            ;Column counter
  108. att_nor    db    0            ;Video attributes - normal
  109. att_hig    db    0            ;                   highlite
  110. att_err    db    0            ;                   error
  111.     
  112. ;    Error window background
  113.  
  114. err_top    db    213, 8 dup (205), 7 dup (' '), 8 dup (205), 184, '$'
  115. err_mid    db    179, 23 dup (' '), 179, '$'
  116. err_bot    db    212, 23 dup (205), 190, '$'
  117. err_nam    db    'ERROR$'
  118.  
  119. ;    Critical Error Handler Messages
  120.     
  121. ;        |<--   width = 23   --->|    Lower byte of reg di
  122.  
  123. ERR_SIZ    equ    24            ;Length of each error message inc $
  124.  
  125. errors    db    '    Write Protected    $'    ;0
  126.     db    '    Unknown Device     $'    ;1
  127.     db    '    Drive Not Ready    $'    ;2
  128.     db    '    Unknown Command    $'    ;3
  129.     db    '   Data Error  (CRC)   $'    ;4
  130.     db    '   Request Structure   $'    ;5
  131.     db    '      Seek Error       $'    ;6
  132.     db    '     Unknown Media     $'    ;7
  133.     db    '   Sector Not Found    $'    ;8
  134.     db    '     Out of Paper      $'    ;9
  135.     db    '      Write Fault      $'    ;a
  136.     db    '      Read Fault       $'    ;b
  137.     db    '    General Failure    $'    ;c
  138.     db    '      (reserved)       $'    ;d
  139.     db    '      (reserved)       $'    ;e
  140.     db    '  Invalid Disk Change  $'    ;f
  141.  
  142. ;    Actions
  143.  
  144. actions    db    'Ignore Retry Abort Fail$'
  145.  
  146. ignor_c    db    'I$'
  147. retry_c    db    'R$'
  148. abort_c    db    'A$'
  149. fail_c  db    'F$'
  150.  
  151. I_POS    equ    1            ;Position of I in Ignore to highlite
  152. R_POS    equ    8            ;Position of R in Retry to highlite
  153. A_POS    equ    14            ;Position of A in Abort to highlite
  154. F_POS    equ    20            ;Position of F in Fail to highlite
  155.  
  156. ;    Install critical error handler and stay resident
  157.  
  158. start:    mov    ax, @DATA        ;Initialize DS
  159.     mov    ds, ax
  160.     mov    ah, DISPSTR        ;Display logon message
  161.     mov    dx, offset logon
  162.     int    DOS
  163.     call    install            ;Install handler and tick watch
  164.     mov    ax, sp            ;Determine paragraphs to keep
  165.     mov    cs:our_sp, ax        ; also save sp for the handler
  166. ;fortunately there should be no fatal errors untill this TSR's    
  167.     mov    cl, 4            ;starting with para's in stack
  168.     shr    ax, cl
  169.     mov    bx, ss            ;Add that to stack segment
  170.     mov    cs:our_ss, bx        ; also save ss for the handler     
  171.     add    ax, bx
  172.     mov    bx, es            ;Then subtract PSP segment
  173.     sub    ax, bx
  174.     inc    ax            ;Add 1 para for safety
  175.     mov    dx, ax
  176.     mov    ax, KEEPPGM        ;TSR with code 0
  177.     int    DOS    
  178.     
  179. ;    Link vector check routine into timer interupt
  180.  
  181. install    proc
  182.     push    ds
  183.     push    es
  184.     push    cs
  185.     pop    ds
  186.     mov    ax, (GETVECT+CRITIC)    ;Read existing INT 24 vector    
  187.     int    DOS
  188.     mov    crt_off, bx
  189.     mov    crt_seg, es
  190.     mov    ax, (SETVECT+CRITIC)    ;Set new INT 24 vector    
  191.     mov    dx, offset crit_handler
  192.     int    DOS
  193.     mov    ax, (GETVECT+TICK)    ;Read existing INT 8 vector    
  194.     int    DOS
  195.     mov    tic_off, bx
  196.     mov    tic_seg, es
  197.     mov    ax, (SETVECT+TICK)    ;Set new INT 8 vector    
  198.     mov    dx, offset vect_check
  199.     int    DOS
  200.     pop    es
  201.     pop    ds
  202.     ret
  203. install    endp
  204.  
  205. ;    Remove critical error handler from interrupt
  206.  
  207. remove    proc
  208.     push    ds
  209.     push    cs
  210.     pop    ds
  211.     mov    dx, tic_off
  212.     mov    ax, (SETVECT+TICK)
  213.     int    DOS
  214.     mov    dx, crt_off
  215.     mov    ax, (SETVECT+CRITIC)
  216.     int    DOS
  217.     pop    ds
  218.     ret
  219. remove    endp
  220.  
  221. ;    Vector check
  222.  
  223. vect_check    proc
  224.     sti
  225.     push    ax
  226.     push    bx
  227.     push    es
  228.     xor    ax, ax            ;Get current INT 24 Vector
  229.     mov    es, ax
  230.     mov    bx, es:[CRITIC*4]
  231.     mov    ax, es:[CRITIC*4+2]
  232.     cmp    ax, seg crit_handler    ;Does it point to our handler
  233.     jne    revect
  234.     cmp    bx, offset crit_handler
  235.     je    chkend
  236. revect: cmp    ax, seg crit_handler    ;Don't revector programs loaded after
  237.     ja    chkend            ; this program
  238.     mov    cs:crt_off, bx        ;If not, save current vector
  239.     mov    cs:crt_seg, ax
  240.     cli                ;then revector it to our handler
  241.     mov    es:[CRITIC*4], offset crit_handler
  242.     mov    es:word ptr [CRITIC*4+2], seg crit_handler
  243.     sti    
  244. chkend:    pop    es
  245.     pop    bx
  246.     pop    ax
  247.     jmp    dword ptr cs:[tic_off]    ;Chain to previous tick handler
  248. vect_check    endp
  249.  
  250.  
  251. ;    Critical error interrupt handler
  252.  
  253. crit_handler    proc 
  254.     sti                ;Enable interupts again
  255.     push    ds            ;Save caller's data segment
  256.     push    cs            ;data segment=codeseg
  257.     pop    ds
  258.     mov    sav_ss, ss        ;Save caller's stack
  259.     mov    sav_sp, sp
  260.     cli                ;Set up local stack
  261.     mov    ss, our_ss
  262.     mov    sp, our_sp
  263.     sti
  264.     push    bx            ;Save required regs on local stack
  265.     push    cx
  266.     push    dx
  267.     push    bp
  268.     push    si
  269.     push    di
  270.     push    es
  271. ;
  272.     mov    err_sta, ax        ;Save error status
  273.     and    di, 00ffh        ;Mask out all but error number
  274.     mov    err_num, di        ;Save error number
  275.     call    vid_mod            ;Get video mode
  276.     cmp    al, 3            ;If mode 0-3 it's text
  277.     jle    text
  278.     mov    att_nor, MO_NORM    ;Only remaining text mode is mono
  279.     mov    att_hig, MO_HIGH    ;so set attributes just in case
  280.     mov    att_err, MO_ERRO
  281.     cmp    al, 7            ;If it is monochrome mode
  282.     je    mode_ok            ;then all set
  283. ;
  284.     call    get_act            ;Get action - no window in graphics
  285.     jmp    done            ;Return with action code
  286. ;
  287. text:    mov    att_nor, BW_NORM    ;Assume B/W attributes
  288.     mov    att_hig, BW_HIGH
  289.     mov    att_err, BW_ERRO
  290.     test    al, 1            ;unless it's a color mode 
  291.     je    mode_ok
  292. ;
  293. color:    mov    att_nor, CO_NORM    ;then use color attributes
  294.     mov    att_hig, CO_HIGH
  295.     mov    att_err, CO_ERRO
  296. ;
  297. mode_ok:call    cur_off            ;Turn cursor off
  298.     call    sav_scr            ;Save underlying screen
  299. ;   display window background and name
  300.     mov    bl, att_nor        ;Use normal attribute for window
  301.     mov    bp, offset err_top    ;Display top line of window
  302.     mov    dh, LINE        ;Top line of window
  303.     mov    dl, COLUMN        ;Left column of window
  304.     call    str_out            ;Display this line
  305.     mov    bp, offset err_mid    ;Display middle 2 lines (less text)
  306.     inc    dh            ;on next line
  307.     mov    dl, COLUMN        ;Yes! We have to keep setting it!
  308.     call    str_out
  309.     mov    bp, offset err_mid    ;and the one following
  310.     inc    dh
  311.     mov    dl, COLUMN
  312.     call    str_out
  313.     mov    bp, offset err_bot    ;Display bottom line
  314.     inc    dh
  315.     mov    dl, COLUMN
  316.     call    str_out
  317.     mov    bl, att_err        ;Use highlite attribute
  318.     mov    bp, offset err_nam    ;Display window name - "ERROR"
  319.     mov    dl, COLUMN+10        ;In middle of top line
  320.     mov    dh, LINE
  321.     call    str_out
  322. ;   Display appropriate error message
  323.     mov    ax, err_num        ;Calculate start of message
  324.     mov    bl, ERR_SIZ        ;Where each message is ERR_SIZ long
  325.     mul    bl
  326.     add    ax, offset errors    ;and the table base is "errors"
  327.     mov    bp, ax
  328.     mov    bl, att_nor        ;Use normal attributes
  329.     mov    dh, LINE+1        ;Starting on seccond row
  330.     mov    dl, COLUMN+1        ;and the second column
  331.     call    str_out            ;Display it
  332. ;   Display allowed actions
  333.     mov    bl, att_nor        ;Normal attr for all but R & I
  334.     mov    dh, LINE+2        ;Line where actions are displayed
  335.     mov    dl, COLUMN+1        ;Column where actions are displ.
  336.     mov    bp, offset actions    ;Display actions
  337.     call    str_out
  338.     mov    dl, COLUMN+I_POS    ;Overlay highlited "I"
  339.     mov    bp, offset ignor_c    
  340.     mov    bl, att_hig
  341.     call    str_out
  342.     mov    dl, COLUMN+R_POS    ;Overlay highlited "R"
  343.     mov    bp, offset retry_c
  344.     mov    bl, att_hig
  345.     call    str_out
  346.     mov    dl, COLUMN+A_POS    ;Overlay highlited "A"
  347.     mov    bp, offset abort_c    
  348.     mov    bl, att_hig
  349.     call    str_out
  350.     mov    dl, COLUMN+F_POS    ;Overlay highlited "F"
  351.     mov    bp, offset fail_c
  352.     mov    bl, att_hig
  353.     call    str_out
  354. ;   Convert error number to DOS standard
  355.     add    err_num, 19
  356. ;   Get desired action from user
  357.     call    get_act            ;Get desired action from user
  358.     push    ax            ;Save action code
  359.     call    res_scr            ;Restore screen under window
  360.     call    cur_on            ;Restore original cursor
  361.     pop    ax            ;Restore action code
  362.     mov    bx, err_sta        ;Restore original error status
  363.     mov    bl, al            ;with new action code
  364.     mov    ax, bx
  365. ;
  366. done:    pop    es            ;Restore registers from local stack
  367.     pop    di
  368.     pop    si
  369.     pop    bp
  370.     pop    dx
  371.     pop    cx
  372.     pop    bx
  373.     cli                ;int's off...just in case
  374.     mov    ss, sav_ss        ;Restore caller's stack
  375.     mov    sp, sav_sp        
  376.     sti
  377.     pop    ds
  378.     iret                ;At this point al contains action
  379. crit_handler    endp    
  380.  
  381. ;    Get video mode
  382.  
  383. vid_mod    proc
  384.     mov    ah, GETMODE        ;Get video page
  385.     int    VIDEO
  386.     mov    scr_pag, bh
  387.     ret
  388. vid_mod    endp
  389.  
  390. ;    Turn cursor off
  391.  
  392. cur_off    proc
  393.     mov    bh, scr_pag        ;Get cursor information
  394.     mov    ah, READCUR
  395.     int    VIDEO
  396.     cmp    cx, 0067h        ;Test for BIOS bug
  397.     jne    cur_ok
  398.     mov    cx, 0607h        ;fix it if required
  399. cur_ok:    mov    old_cur, cx        ;Save cursor scan lines
  400.     mov    old_pos, dx        ;Save cursor position
  401.     mov    ah, SETSIZE        ;Set cursor off
  402.     mov    cx, NOCURS
  403.     int    VIDEO
  404.     ret
  405. cur_off endp
  406.  
  407. ;   Turn cursor back on
  408.  
  409. cur_on    proc
  410.     mov    dx, old_pos        ;Restore original cursor position
  411.     mov    bh, scr_pag
  412.     mov    ah, SETPOS
  413.     int    VIDEO
  414.     mov    cx, old_cur        ;Restor original scan lines
  415.     mov    ah, SETSIZE
  416.     int    VIDEO
  417.     ret
  418. cur_on    endp
  419.  
  420. ;   Save the screen area under the window
  421.  
  422. sav_scr    proc
  423.     mov    al, LINE        ;Starting at LINE
  424.     mov    line_c, al
  425.     xor    di, di            ;Point to start of scr_save
  426.     mov    cx, LINES        ;For each line
  427. lin_loo:push    cx
  428.     mov    cx, COLUMNS        ;For each column
  429.     mov    al, COLUMN        ;Starting at COLUMN
  430.     mov    colum_c, al
  431. col_loo:mov    ah, SETPOS        ;Set position to read
  432.     mov    bh, scr_pag
  433.     mov    dh, line_c
  434.     mov    dl, colum_c
  435.     int    VIDEO
  436.     mov    ah, READCHR        ;Read character & attribute
  437.     mov    bh, scr_pag
  438.     int    VIDEO
  439.     mov    scr_sav[di], ah        ;Place attribute in scr_sav
  440.     inc    di            ;Bump scr_sav pointer
  441.     mov    scr_sav[di], al        ;Place character in scr_sav
  442.     inc    di
  443.     inc    colum_c            ;Bump column pointer
  444.     loop    col_loo            ;Till line is done
  445.     inc    line_c            ;Bump line pointer
  446.     pop    cx            ;Till window done
  447.     loop    lin_loo
  448.     ret
  449. sav_scr    endp
  450.  
  451. ;    Restore the area under the window
  452.  
  453. res_scr    proc    near
  454.     mov    al, LINE        ;Starting at LINE
  455.     mov    line_c, al
  456.     xor    di, di            ;Point to start of scr_sav
  457.     mov    cx, LINES        ;For each line
  458. lin_lo2:push    cx
  459.     mov    cx, COLUMNS        ;For each column
  460.     mov    al, COLUMN        ;Point to starting column
  461.     mov    colum_c, al
  462. col_lo2:mov    ah, SETPOS        ;Set position to restore
  463.     mov    bh, scr_pag
  464.     mov    dh, line_c
  465.     mov    dl, colum_c
  466.     int    VIDEO
  467.     push    cx
  468.     mov    ah, WRITCHR        ;Write character & attribute
  469.     mov    bl, scr_sav[di]        ;Get attribute
  470.     inc    di            ;Bump scr_sav pointer
  471.     mov    al, scr_sav[di]        ;Get character
  472.     inc    di            ;Bump scr_sav pointer
  473.     mov    bh, scr_pag        ;Ensure we have correct page
  474.     mov    cx, 1            ;This character just once
  475.     int    VIDEO
  476.     pop    cx
  477.     inc    colum_c            ;Bump column pointer
  478.     loop    col_lo2            ;Till line is done
  479.     inc    line_c            ;Bump line pointer
  480.     pop    cx            ;Till window done
  481.     loop    lin_lo2
  482.     ret
  483. res_scr    endp
  484.  
  485. ;   Display string - till '$' - No Wrap Allowed!
  486.  
  487. ;    call with: bp = pointer to string
  488. ;        bl = attribute
  489. ;        dh = screen row
  490. ;        dl = starting column
  491.  
  492. str_out    proc
  493.     push    di            ;We must save di reg
  494.     push    ax            ;and ax reg
  495.     mov    bh, scr_pag        ;Position cursor
  496.     mov    ah, SETPOS
  497.     int    VIDEO
  498.     xor    di, di            ;Point to start of string
  499. str_loo:mov    al, cs:[bp][di]        ;Get current character
  500.     cmp    al, '$'            ;Check for end of string
  501.     je    str_end
  502.     mov    cx, 1            ;Only 1 of each character
  503.     mov    ah, WRITCHR        ;Write character to screen
  504.     int    VIDEO
  505.     inc    dl            ;Point to next column
  506.     mov    ah, SETPOS        ;Move cursor there
  507.     int    VIDEO
  508.     inc    di            ;Point to next character in string
  509.     jmp    str_loo            ;continue
  510. ;
  511. str_end:pop    ax            ;Restore ax reg
  512.     pop    di            ;and di reg
  513.     ret
  514. str_out    endp
  515.  
  516. ;    Obtain response from user - Test for valid action
  517. ;    when valid is specified set return code in al reg
  518.  
  519. get_act    proc
  520.     push    cx
  521. action:    call    alert            ;Alert user
  522. ;   Clear keyboard buffer
  523. tst_kbd:mov    ah, TESTKBD        ;Any characters in keyboard buffer?
  524.     int    KEYBRD
  525.     jz    buf_clr            ;If nothing in buffer then it's clr
  526.     mov    ah, READKBD        ;else dump this keypress
  527.     int    KEYBRD
  528.     jmp    tst_kbd
  529. buf_clr:
  530. ;   Get a new keypress
  531. key_psd:mov    ah,    TESTKBD        ;Any key pressed yet
  532.     int    KEYBRD
  533.     jz    key_psd            ;If not then wait
  534.     mov    ah, READKBD        ;else get keypress
  535.     int    KEYBRD
  536.     and    al, 0DFh        ;Convert to lower case
  537. ;   Test for valid key
  538.     xor    cx, cx
  539.     cmp    al, 'I'            ;Test if 'I' pressed
  540.     je    goodkey
  541.     inc    cl                
  542.     cmp    al, 'R'            ;Test if 'R' pressed
  543.     je    goodkey
  544.     inc    cl
  545.     cmp    al, 'A'            ;Test if 'A' pressed
  546.     je    goodkey
  547.     inc    cl
  548.     cmp    al, 'F'            ;Test if 'F' pressed
  549.     je    goodkey
  550.     jmp    action    
  551. goodkey:mov    al, cl
  552.     pop    cx
  553.     ret
  554. get_act    endp
  555.  
  556. ;    Alert user with low beep tone
  557.  
  558. alert    proc
  559.     push    bx
  560.     push    di
  561.     mov    bx,     ALERT_D        ;Duration of alert tone
  562.     mov    di,     ALERT_F        ;Frequency of alert tone
  563.     call    abeep
  564.     pop    di
  565.     pop    bx
  566.     ret
  567. alert    endp
  568.  
  569. ;    Produce Beep
  570. ;        BX = Duration
  571. ;        DI = Frequency
  572.  
  573. abeep    proc
  574.     push    ax
  575.     push    bx
  576.     push    cx
  577.     push    dx
  578.     push    di
  579.     mov    al,     0B6h
  580.     out    43h,    al
  581.     mov    dx,     14h
  582.     mov    ax,     4F38h
  583.     div    di
  584.     out    42h,    al
  585.     mov    al,     ah
  586.     out    42h,    al
  587.     in    al,     61h
  588.     mov    ah,     al
  589.     or    al,     3
  590.     out    61h,    al
  591. delay:    mov    cx,     2801
  592. tone:    loop    tone
  593.     dec    bx
  594.     jnz    delay
  595.     mov    al,     ah
  596.     out    61h,    al
  597.     pop    di
  598.     pop    dx
  599.     pop    cx
  600.     pop    bx
  601.     pop    ax
  602.     ret
  603. abeep    endp
  604.  
  605.      END    start
  606.