home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cdrom.zip / DDK / BASE / SRC / DEV / DASD / CDROM / ATAPI / dprintf.asm < prev    next >
Encoding:
Assembly Source File  |  1998-04-10  |  15.5 KB  |  586 lines

  1. ;
  2. ;****************************************************************************
  3. ;*
  4. ;* dprintf - this routine displays information on the debug terminal. it
  5. ;*         provides limited formatting, which is a subset of c's printf
  6. ;*         function
  7. ;*
  8. ;*    calling sequence:    push selector for insert 'n'
  9. ;*                push offset for insert 'n'
  10. ;*                push selector for 'n-1'
  11. ;*                push offset for 'n-1'
  12. ;*                   ...
  13. ;*                push selector for second insert
  14. ;*                push offset for second insert
  15. ;*                push selector for first insert
  16. ;*                push offset for first insert
  17. ;*                push selector raw string
  18. ;*                push offset for raw string
  19. ;*                call dprintf
  20. ;*                add sp,4 + ('n' * 4)
  21. ;*
  22. ;*            for "%w", just push one word containing the data to
  23. ;*                  be displayed. make sure that the "add sp"
  24. ;*                  cleans the stack correctly.
  25. ;*
  26. ;*            for "%z", just the repeat count, then the selector
  27. ;*                  of the area to display, and then the offset.
  28. ;*                  make sure that the "add sp" cleans the stack
  29. ;*                  correctly.
  30. ;*
  31. ;*    formatting:    prior to being displayed, the raw string is formatted
  32. ;*            by scanning it for format control sequences. as each
  33. ;*            format control sequence is encountered, it is replaced
  34. ;*            by appropriately formatted text obtained from the
  35. ;*            corresponding pointer
  36. ;*
  37. ;*            the following format control sequences are supported:
  38. ;*
  39. ;*            %c -  the corresponding far ptr points to a byte
  40. ;*                  which replaces the "%c"
  41. ;*
  42. ;*            %u -  the corresponding far ptr points to a word
  43. ;*                  which is displayed as an unsigned decimal
  44. ;*                  integer, replacing the "%u"
  45. ;*
  46. ;*            %x -  the corresponding far ptr points to a word
  47. ;*                  which is displayed as upper case hex,
  48. ;*                  replacing the "%X"
  49. ;*
  50. ;*            %lx - the corresponding far ptr points to a double
  51. ;*                  word which is displayed as upper case hex,
  52. ;*                  replacing the "%X"
  53. ;*
  54. ;*            %s -  the corresponding far ptr points to a null
  55. ;*                  terminated string which is displayed unchanged,
  56. ;*                  replacing the "%s"
  57. ;*
  58. ;*            %p -  the corresponding far ptr is displayed as upper
  59. ;*                  case hex in the format "ssss:oooo"
  60. ;*
  61. ;*            %w -  the corresponding word is displayed as upper
  62. ;*                  case hex replacing the "%w". note that in this
  63. ;*                  case, only one word is pushed onto the stack
  64. ;*                  for the %w insert
  65. ;*
  66. ;*            %z -  using the corresponding repeat count and far
  67. ;*                  pointer, a memory dump is produced. note that
  68. ;*                  in this case the stack contains a repeat count
  69. ;*                  and a far pointer to the area to dump
  70. ;*
  71. ;*            %% -  the character "%" is displayed, replacing the
  72. ;*                  "%%"
  73. ;*
  74. ;*
  75.  
  76.  
  77. .286p
  78.  
  79.  
  80. COM1_PORT    EQU    03f8h
  81. COM2_PORT    EQU    02f8h
  82.  
  83.  
  84. DEFAULT_PORT    EQU    COM1_PORT
  85.  
  86. CAR_RET     EQU    0DH
  87. LINE_FEED    EQU    0AH
  88. BELL        EQU    07H
  89. COM_LSR     EQU    05H
  90. COM_DAT     EQU    00H
  91.  
  92.  
  93.  
  94. s_frame     struc
  95.  
  96. s_bp        dw    ?        ; callers bp.
  97. s_ptr_delta    dw    ?        ; delta (in bytes) to current pointer
  98.                     ; from first pointer.
  99. s_ret        dw    ?        ; callers ip.
  100. s_string    dd    ?        ; far pointer to raw string.
  101. s_ptrs        dd    ?        ; pointer to first variable.
  102.  
  103. s_frame     ends
  104.  
  105. ;word_10000     dw     10000
  106. ;word_1000     dw     1000
  107. ;word_100     dw     100
  108. ;word_10     dw     10
  109.  
  110.  
  111. _DATA           segment dword public 'DATA'
  112.  
  113.                 extrn  _ComPort:word
  114.  
  115. _DATA           ends
  116.  
  117.  
  118. _TEXT    segment dword public 'code'
  119.     assume    cs:_TEXT,ds:_DATA
  120.  
  121. _dprintf    proc    near
  122.         public    _dprintf
  123.  
  124.  
  125.         push    0        ; zero the delta to current pointer.
  126.  
  127.         push    bp        ; save our callers bp register.
  128.         mov    bp,sp        ; point to our stack frame.
  129.  
  130.         push    ds        ; save our callers ds register.
  131.         push    es        ; save our callers es register.
  132.         pusha            ; save all other caller registers.
  133.         pushf
  134.         cli
  135.  
  136.         lds    si,ss:[bp+s_string] ; point to the raw string.
  137.  
  138. dprintf_loop:    lodsb            ; pick up a byte of the string.
  139.  
  140.         or    al,al        ; is it the end of the string?
  141.         jnz    dprintf_more    ; no, go check for format control.
  142.  
  143.         popf
  144.         popa            ; restore all other caller registers.
  145.         pop    es        ; restore our callers es register.
  146.         pop    ds        ; restore our callers ds register.
  147.         pop    bp        ; restore our callers bp register.
  148.         add    sp,2        ; unstack s_ptr_delta.
  149.  
  150.         ret            ; return to our caller.
  151.  
  152. dprintf_more:    cmp    al,'%'          ; no, is it the start of a format
  153.                     ; control sequence?
  154.         je    dprintf_type    ; yes, go see what type of sequence.
  155.         jmp    dprintf_put_ch    ; no, go display character and return.
  156.  
  157. dprintf_type:    lodsb            ; pick up a byte of the string.
  158.         cmp    al,'%'          ; is caller trying to display "%"?
  159.  
  160.         jne    dprintf_try_c    ; no, go see if it is a "c".
  161.  
  162.         mov    al,'%'          ; yes, go display it
  163.         jmp    dprintf_put_ch    ; and exit.
  164.  
  165. dprintf_try_c:    cmp    al,'c'          ; is it a string display?
  166.         jne    dprintf_try_s    ; no, go see if it is a "s".
  167.  
  168.         lea    bx,[bp]+s_ptrs           ; yes, pick up the
  169.         add    bx,ss:[bp+s_ptr_delta] ; corresponding
  170.         les    bx,ss:[bx]           ; pointer.
  171.         add    ss:[bp+s_ptr_delta],4  ; move down to next pointer.
  172.  
  173.         mov    al,es:[bx]    ; pick up a byte.
  174.         jmp    dprintf_put_ch    ; go display character and return.
  175.  
  176. dprintf_try_s:    cmp    al,'s'          ; is it a string display?
  177.         jne    dprintf_try_u    ; no, go see if it is a "u".
  178.  
  179.         lea    bx,[bp]+s_ptrs           ; yes, pick up the
  180.         add    bx,ss:[bp+s_ptr_delta] ; corresponding
  181.         les    bx,ss:[bx]           ; pointer.
  182.         add    ss:[bp+s_ptr_delta],4  ; move down to next pointer.
  183.  
  184. dprintf_next_s: mov    al,es:[bx]    ; pick up a byte.
  185.  
  186.         or    al,al        ; is it the end of the string?
  187.         jz    dprintf_loop    ; yes, go do next raw string byte.
  188.  
  189.         call    put_char    ; no, display the character.
  190.  
  191.         inc    bx        ; move down to the next character
  192.         jmp    dprintf_next_s    ; and go round again.
  193.  
  194. dprintf_try_u:    cmp    al,'u'          ; is it an unsigned short display?
  195.         jne    dprintf_try_x    ; no, go see if it is a "X".
  196.  
  197.         lea    bx,[bp]+s_ptrs           ; yes, pick up the
  198.         add    bx,ss:[bp+s_ptr_delta] ; corresponding
  199.         les    bx,ss:[bx]           ; pointer.
  200.         add    ss:[bp+s_ptr_delta],4  ; move down to next pointer.
  201.  
  202.         mov    ax,es:[bx]    ; pick up the word to display.
  203.  
  204.         xor    dx,dx        ; convert the
  205.         mov    cx, 10000
  206.         div    cx        ; ten thousands
  207. ;        div    word_10000    ; ten thousands
  208.         or    al,'0'          ; digit and
  209.         call    put_char    ; display it.
  210.  
  211.         mov    ax,dx        ; convert the
  212.         xor    dx,dx        ; thousands
  213.         mov    cx, 1000
  214.         div    cx        ; digit
  215. ;        div    word_1000    ; digit
  216.         or    al,'0'          ; and
  217.         call    put_char    ; display it.
  218.  
  219.         mov    ax,dx        ; convert the
  220.         xor    dx,dx        ; hundreds
  221.         mov    cx, 100
  222.         div    cx        ; digit
  223. ;        div    word_100    ; digit
  224.         or    al,'0'          ; and
  225.         call    put_char    ; display it.
  226.  
  227.         mov    ax,dx        ; convert the
  228.         xor    dx,dx        ; tens
  229.         mov    cx, 10
  230.         div    cx        ; digit
  231. ;        div    word_10     ; digit
  232.         or    al,'0'          ; and
  233.         call    put_char    ; display it.
  234.  
  235.         mov    al,dl        ; convert the units digit
  236.         or    al,'0'          ; and go display it
  237.         jmp    dprintf_put_ch    ; and return.
  238.  
  239. dprintf_try_x:    cmp    al,'x'          ; is it an unsigned short hex display?
  240.         jne    dprintf_try_lx    ; no, go see if it is a "lX".
  241.  
  242.         lea    bx,[bp]+s_ptrs           ; yes, pick up the
  243.         add    bx,ss:[bp+s_ptr_delta] ; corresponding
  244.         les    bx,ss:[bx]           ; pointer.
  245.         add    ss:[bp+s_ptr_delta],4  ; move down to next pointer.
  246.  
  247.         call    put_hex_word    ; convert and display the word.
  248.  
  249.         jmp    dprintf_loop    ; go do next raw string byte.
  250.  
  251. dprintf_try_lx: cmp    al,'l'          ; is it an unsigned long hex display?
  252.         jne    dprintf_try_p    ; no, go see if it is a "p".
  253.         lodsb            ; maybe, pick up a byte of the string.
  254.         cmp    al,'x'          ; is the second byte correct?
  255.         je    dprintf_do_lx    ; no, go report
  256.         jmp    dprintf_error    ; the error.
  257.  
  258. dprintf_do_lx:    lea    bx,[bp]+s_ptrs           ; yes, pick up the
  259.         add    bx,ss:[bp+s_ptr_delta] ; corresponding
  260.         les    bx,ss:[bx]           ; pointer.
  261.         add    ss:[bp+s_ptr_delta],4  ; move down to next pointer.
  262.  
  263.         add    bx,2        ; move down to the second word.
  264.         call    put_hex_word    ; convert and display the second word.
  265.         sub    bx,2        ; move back to the first word.
  266.         call    put_hex_word    ; convert and display the first word.
  267.  
  268.         jmp    dprintf_loop    ; go do next raw string byte.
  269.  
  270. dprintf_try_p:    cmp    al,'p'          ; is it a far pointer display?
  271.         jne    dprintf_try_w    ; no, go see if it is a "w".
  272.  
  273.         lea    bx,[bp]+s_ptrs           ; yes, pick up the
  274.         add    bx,ss:[bp+s_ptr_delta] ; corresponding pointer.
  275.         add    ss:[bp+s_ptr_delta],4  ; move down to next pointer.
  276.  
  277.         push    es        ; save the callers data selector.
  278.  
  279.         push    ss        ; set up the proper
  280.         pop    es        ; selector.
  281.  
  282.         add    bx,2        ; move down to the second word.
  283.         call    put_hex_word    ; convert and display the selector.
  284.         mov    al,':'          ; display
  285.         call    put_char    ; the ":".
  286.         sub    bx,2        ; move back to the first word.
  287.         call    put_hex_word    ; convert and display the offset.
  288.  
  289.         mov    al,' '          ; display
  290.         call    put_char    ; a couple
  291.         mov    al,' '          ; of
  292.         call    put_char    ; spaces.
  293.  
  294.         pop    es        ; recover the callers data selector.
  295.  
  296.         jmp    dprintf_loop    ; go do next raw string byte.
  297.  
  298. dprintf_try_w:    cmp    al,'w'          ; is it an immediate word display?
  299.         jne    dprintf_try_z    ; no, go see if it is a "z".
  300.  
  301.         lea    bx,[bp]+s_ptrs           ; yes, pick up the
  302.         add    bx,ss:[bp+s_ptr_delta] ; corresponding pointer.
  303.         add    ss:[bp+s_ptr_delta],2  ; move down to next pointer.
  304.  
  305.         push    es        ; save the callers data selector.
  306.  
  307.         push    ss        ; set up the proper
  308.         pop    es        ; selector.
  309.  
  310.         call    put_hex_word    ; convert and display the word.
  311.  
  312.         pop    es        ; recover the callers data selector.
  313.  
  314.         jmp    dprintf_loop    ; go do next raw string byte.
  315.  
  316. dprintf_try_z:    cmp    al,'z'          ; is it a memory dump display?
  317.         je    dprintf_do_z    ; no, go report
  318.         jmp    dprintf_error    ; the error.
  319.  
  320. dprintf_do_z:
  321.         lea    bx,[bp]+s_ptrs           ; yes, pick up the
  322.         add    bx,ss:[bp+s_ptr_delta] ; corresponding pointer.
  323.         add    ss:[bp+s_ptr_delta],6  ; move down to next pointer.
  324.  
  325.         mov    cx,ss:[bx+4]    ; pick up the repeat count.
  326.  
  327.         push    es        ; save the callers data selector.
  328.  
  329.         les    bx,ss:[bx]    ; point to the area to display.
  330.  
  331. dprintf_z_a:    mov    ax,es        ; pick up the selector to display.
  332.         xchg    ah,al        ; set up to process the first byte.
  333.         call    put_left_nib    ; display the first byte
  334.         call    put_right_nib    ; of the selector.
  335.         xchg    ah,al        ; set up to process the second byte.
  336.         call    put_left_nib    ; display the second byte
  337.         call    put_right_nib    ; of the selector.
  338.  
  339.         mov    al,':'          ; display a
  340.         call    put_char    ; colon.
  341.  
  342.         mov    ax,bx        ; pick up the offset to display.
  343.         xchg    ah,al        ; set up to process the first byte.
  344.         call    put_left_nib    ; display the first byte
  345.         call    put_right_nib    ; of the offset.
  346.         xchg    ah,al        ; set up to process the second byte.
  347.         call    put_left_nib    ; display the second byte
  348.         call    put_right_nib    ; of the offset.
  349.  
  350.         mov    al,' '          ; display
  351.         call    put_char    ; two
  352.         mov    al,' '          ; seperating
  353.         call    put_char    ; spaces.
  354.  
  355.         push    cx        ; save the repeat count for later.
  356.  
  357.         mov    dx,16*3+1    ; initialize the fill count.
  358.  
  359.         cmp    cx,16        ; are there more than 16 bytes left?
  360.         jbe    dprintf_z_b    ; yes, limit it to 16 bytes
  361.         mov    cx,16        ; for this line.
  362.  
  363. dprintf_z_b:    push    bx        ; save offset and display count
  364.         push    cx        ; for the character display.
  365.  
  366. dprintf_z_c:    mov    al,es:[bx]    ; pick up a byte to display.
  367.         call    put_hex_byte    ; display it in hex.
  368.  
  369.         mov    al,' '          ; set up to display a space.
  370.         cmp    dx,9*3+1    ; should it be a dash?
  371.         jne    dprintf_z_e    ; no, bypass changing it.
  372.         mov    al,'-'          ; yes, set up to display a dash.
  373. dprintf_z_e:    call    put_char    ; display the dash or space.
  374.  
  375.         sub    dx,3        ; down the fill count by one position.
  376.  
  377.         inc    bx        ; move down to the next byte.
  378.  
  379.         loop    dprintf_z_c    ; more to do? yes, go round again?
  380.  
  381.         mov    cx,dx        ; no, pick up remaining fill count.
  382.  
  383. dprintf_z_g:    mov    al,' '          ; display a
  384.         call    put_char    ; space.
  385.  
  386.         loop    dprintf_z_g    ; more to do? yes, go round again.
  387.  
  388.         pop    cx        ; recover the offset and
  389.         pop    bx        ; display count.
  390.  
  391. dprintf_z_i:    mov    al,'.'          ; set up to display a dot.
  392.  
  393.         mov    ah,es:[bx]    ; does the byte
  394.         cmp    ah,20h        ; contain a
  395.         jb    dprintf_z_k    ; valid ascii
  396.         cmp    ah,7fh        ; code?
  397.         ja    dprintf_z_k    ; no, go display the dot.
  398.  
  399.         xchg    al,ah        ; yes, set up to do byte's contents.
  400.  
  401. dprintf_z_k:    call    put_char    ; display a dot or the byte contents.
  402.  
  403.         inc    bx        ; move down to the next byte.
  404.  
  405.         loop    dprintf_z_i    ; more to do on this line?
  406.                     ; yes, go round again.
  407.  
  408.         pop    cx        ; no, recover the repeat count.
  409.  
  410.         sub    cx,16        ; down the repeat count by one line.
  411.  
  412.         jle    dprintf_z_z    ; more to do? no, go exit.
  413.  
  414.         mov    al,CAR_RET    ; perform
  415.         call    put_char    ; a
  416.         mov    al,LINE_FEED    ; new line
  417.         call    put_char    ; operation.
  418.  
  419.         jmp    dprintf_z_a    ; go round and display another line.
  420.  
  421. dprintf_z_z:    pop    es        ; recover the callers data selector.
  422.  
  423.         jmp    dprintf_loop    ; go do next raw string byte.
  424.  
  425. dprintf_error:    mov    ah,al        ; display
  426.         mov    al,'?'          ; an
  427.         call    put_char    ; eye
  428.         mov    al,'\'          ; catching
  429.         call    put_char    ; "invalid
  430.         mov    al,ah        ; format
  431.         call    put_char    ; control"
  432.         mov    al,'\'          ; message
  433.         call    put_char    ; and
  434.         mov    al,BELL     ; beep.
  435.  
  436. dprintf_put_ch: call    put_char    ; display the character.
  437.         jmp    dprintf_loop    ; go process next raw string byte.
  438.  
  439. _dprintf    endp
  440.  
  441. put_left_nib    proc    near
  442.  
  443.         push    ax        ; save the callers ax register.
  444.  
  445.         shr    al,4        ; convert the
  446.         add    al,'0'          ; left nibble
  447.         cmp    al,'9'          ; to an ascii
  448.         jbe    put_left_nib_a    ; hex
  449.         add    al,'A'-'9'-1    ; representation.
  450. put_left_nib_a: call    put_char    ; display the character.
  451.  
  452.         pop    ax        ; restore the callers ax register.
  453.  
  454.         ret            ; return to our caller.
  455.  
  456. put_left_nib    endp
  457.  
  458. put_right_nib    proc    near
  459.  
  460.         push    ax        ; save the callers ax register.
  461.  
  462.         and    al,0fh        ; convert the
  463.         add    al,'0'          ; right nibble
  464.         cmp    al,'9'          ; to an
  465.         jbe    put_rght_nib_a    ; ascii hex
  466.         add    al,'A'-'9'-1    ; representation.
  467. put_rght_nib_a: call    put_char    ; display the character.
  468.  
  469.         pop    ax        ; restore the callers ax register.
  470.  
  471.         ret            ; return to our caller
  472.  
  473. put_right_nib    endp
  474.  
  475. put_hex_byte    proc    near
  476.  
  477.         mov    al,es:[bx]    ; display the left nibble
  478.         call    put_left_nib    ; in ascii hex.
  479.  
  480.         mov    al,es:[bx]    ; display the right nibble
  481.         call    put_right_nib    ; in ascii hex.
  482.  
  483.         ret            ; return to our caller.
  484.  
  485. put_hex_byte    endp
  486.  
  487.  
  488. put_hex_word    proc    near
  489.  
  490.         inc    bx        ; set up to process second byte first.
  491.  
  492.         call    put_hex_byte    ; display the byte in hex.
  493.  
  494.         dec    bx        ; move back to the first byte.
  495.  
  496.         call    put_hex_byte    ; display the byte in hex.
  497.  
  498.         ret            ; return to our caller.
  499.  
  500. put_hex_word    endp
  501.  
  502.  
  503. ;         public  portadr
  504. ;portadr     dw     DEFAULT_PORT     ; change config.h to change this.
  505.                     ; use: com2=02f8H, com1=03f8H
  506.  
  507. IODelay Macro
  508.     local a
  509.     jmp a
  510. a:
  511. endm
  512.  
  513. PollC    PROC    NEAR
  514.     public    PollC
  515.  
  516. ;    mov    dx, cs:PortAdr
  517.     mov    dx, _ComPort
  518.     add    dx, COM_LSR
  519.  
  520.     in    al,dx            ; get input status
  521. ;    IODelay
  522.  
  523.     and    al,1            ; is there a char in RECV buffer?
  524.     jz    plc1            ; no, go return empty
  525.  
  526. ;    mov    dx, cs:PortAdr
  527.     mov    dx, _ComPort
  528.     add    dx, COM_DAT
  529.  
  530.     in    al,dx            ; suck char out of buffer
  531. ;    IODelay
  532.  
  533.     and    al,07fh         ; strip off stupid parity crap
  534. plc1:    ret
  535. PollC    ENDP
  536.  
  537.  
  538. ;**    PUTC - output a single char to COM2 handling ^S
  539.  
  540.  
  541. put_char    proc    near
  542.         public    put_char
  543.  
  544.     push    dx
  545.     push    ax
  546.  
  547. ;    See if ^S
  548.  
  549.     call    PollC            ; is there a char at input
  550.     jz    pc2            ; no, go output our char
  551.     cmp    al,'S' - 'A' + 1    ; is it ^S?
  552.     jnz    pc2            ; no, go output our char
  553.  
  554. ;    Saw ^S.  Wait for and eat next char.
  555.  
  556. pc1:    call    PollC            ; look for next char
  557.     jz    pc1            ; no char, go look again
  558.     cmp    al,'S' - 'A' + 1    ; is it ^S again?
  559.     jz    pc1            ; yes, go look for something else
  560.  
  561. ;pc2:     mov     dx, cs:PortAdr
  562. pc2:    mov    dx, _ComPort
  563.     add    dx, COM_LSR
  564.     in    al,dx
  565. ;    IODelay
  566.     test    al,020h
  567.     jz    pc2
  568.  
  569. ;    ready.    crank it out!
  570.  
  571. ;    mov    dx, cs:PortAdr
  572.     mov    dx, _ComPort
  573.     add    dx, COM_DAT
  574.     pop    ax
  575.     out    dx,al
  576.  
  577.         pop    dx        ; restore the callers dx register.
  578.  
  579.     ret
  580.  
  581. put_char    endp
  582.  
  583. _TEXT    ends
  584.     end
  585.  
  586.