home *** CD-ROM | disk | FTP | other *** search
/ PC Press: Internet / PC_PRESS.ISO / software / dos / misc / inar-100.exe / SRC / PCROUTE / LOG.INC < prev    next >
Encoding:
Text File  |  1995-05-21  |  18.9 KB  |  734 lines

  1. ;;************************************************************************* 
  2. ;;                     log.inc       log.inc
  3. ;;*************************************************************************
  4. ;;
  5. ;;  Copyright (C) 1989 Northwestern University, Vance Morrison
  6. ;;
  7. ;;
  8. ;; Permission to view, compile, and modify for LOCAL (intra-organization) 
  9. ;; USE ONLY is hereby granted, provided that this copyright and permission 
  10. ;; notice appear on all copies.  Any other use by permission only.
  11. ;;
  12. ;; Northwestern University makes no representations about the suitability 
  13. ;; of this software for any purpose.  It is provided "as is" without expressed 
  14. ;; or implied warranty.  See the copywrite notice file for complete details.
  15. ;;
  16. ;;*****************************************************************************
  17. ;;
  18. ;; log.inc a module that allows significant events to be logged.  It does
  19. ;; this by using the BSD UNIX syslog facility. 
  20. ;;
  21. ;;      This module provides the following functions
  22. ;;
  23. ;; Routines provided by this module
  24. ;;
  25. ;;   LOG_DECLARE name, facility, udp
  26. ;;   LOG_DEFINE_in_AX_BX name, log_host
  27. ;;   LOG_PRINT name, type, severity, string
  28. ;;   LOG_PRINT_REG_HEX  name, type, severity, string, reg
  29. ;;   LOG_PRINT_REG_DEC  name, type, severity, string, reg
  30. ;;   LOG_PRINT_INET_in_AX_BX name, type, severity, string
  31. ;;
  32. ;;  
  33. ;;
  34. ;;*****************************************************************************
  35.  
  36. ;;*****************************************************************************
  37. ;; definition of LOG packet structure
  38.  
  39. SYSLOG_PORT       = 514
  40.  
  41. log_data STRUC
  42.     log_host    DD ?
  43.     log_ip_addr DD ?
  44.     log_mask    DW ?
  45.     log_pri     DW ?
  46. log_data ENDS
  47.  
  48. ;; posible severity levels (see /usr/include/syslogd.h on a unix host)
  49. L_EMERG = 0
  50. L_ALERT = 1
  51. L_CRIT  = 2
  52. L_ERR   = 3
  53. L_WARNING = 4
  54. L_NOTICE  = 5
  55. L_INFO    = 6
  56. L_DEBUG   = 7
  57.  
  58. ;; possible facility types
  59. L_SYS     = 0       ;; system messages
  60. L_ROUTE   = 1       ;; routing messages
  61. L_MON     = 2       ;; monitoring messages
  62.  
  63. ;; posible facilities levels (see /usr/include/syslogd.h on a unix host)
  64. LOG_USER    = 1
  65. LOG_LOCAL0  = 16    ;; this is the recommended one
  66. LOG_LOCAL1  = 17
  67. LOG_LOCAL2  = 18
  68. LOG_LOCAL3  = 19
  69. LOG_LOCAL4  = 20
  70. LOG_LOCAL5  = 21
  71. LOG_LOCAL6  = 22
  72. LOG_LOCAL7  = 23
  73.  
  74.  
  75. ;;******************************************************************************
  76. ;;  LOG_DECLARE name, facility, udp
  77. ;;       LOG_DECLARE delcares a new loging object called 'name'. 
  78. ;;       'facility' is the numeric facility number that is used to
  79. ;;       identify the log messages to syslogd.  16 is local0.  For
  80. ;;       others look in your /usr/include/syslog.h file.
  81. ;;       'udp' is the udp socket listener object.
  82. ;;
  83. LOG_DECLARE   MACRO  name, facility, udp, timer
  84.     .errb <timer>
  85.  
  86.     .DATA
  87.     global log_&name&_data:log_data
  88.     log_&name&_facility = facility
  89.     log_&name&_udp_sock = (name*100+1)
  90.     log_&name&_timer    = timer
  91.  
  92.     .CODE
  93.     global log_&name&_define_in_AX_BX_SI:near
  94.     global log_&name&_print_in_DX_SI_const_ALL:near
  95.     global log_&name&_print_hex_in_AX_DX_SI_const_ALL:near
  96.     global log_&name&_print_dec_in_AX_DX_SI_const_ALL:near
  97.     global log_&name&_print_inet_in_AX_BX_DX_SI_const_ALL:near
  98.  
  99.     global log_&name&_send_syslog_buff_in_CX:near
  100.     global log_&name&_get_syslog_buff_in_DL_out_AX_DI_ES:near
  101.     global log_dec_ascii_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES:near
  102.     global log_hex_ascii_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES:near
  103.     global log_print_str_in_CX_SI_DI_ES_out_DI_CX_const_BX_DX_BP_ES:near
  104.  
  105.     UDP_SOCK_DECLARE %log_&name&_udp_sock, udp, SYSLOG_PORT
  106. ENDM
  107.  
  108.  
  109. ;;******************************************************************************
  110. ;;   LOG_DEFINE_in_AX_BX name
  111. ;;       LOG_DEFINE sets aside the memory and acutally does the 
  112. ;;       initialization for the routeing objects 'name'.  AX holds the
  113. ;;       priority level (only messages with a priority less than this
  114. ;;       value will be logged).  BX holds the logging bitmask  Only those 
  115. ;;       loging types that are  '0' in this  mask will actually be logged.  
  116. ;;       Thus the bitmap DISABLES loging.
  117. ;;
  118. LOG_DEFINE_in_AX_BX   MACRO   name, log_host
  119.     mov SI, offset log_host
  120.     call log_&name&_define_in_AX_BX_SI
  121. ENDM
  122.  
  123. LOG_REAL_DEFINE_in_AX_BX_SI MACRO name
  124.     local around, read_code, timer_code, startup, no_monitor, time_ok
  125.     .errb <name>
  126.  
  127.     .DATA
  128.     log_&name&_data log_data <>
  129.  
  130.     .CODE
  131.     jmp around
  132.                 ;; 'external' routines
  133.         log_&name&_print_in_DX_SI_const_ALL:
  134.            LOG_REAL_PRINT_in_DX_SI_const_ALL name
  135.             RET
  136.         log_&name&_print_hex_in_AX_DX_SI_const_ALL:
  137.            LOG_REAL_PRINT_HEX_in_AX_DX_SI_const_ALL name
  138.             RET
  139.         log_&name&_print_dec_in_AX_DX_SI_const_ALL:
  140.            LOG_REAL_PRINT_DEC_in_AX_DX_SI_const_ALL name
  141.             RET
  142.         log_&name&_print_inet_in_AX_BX_DX_SI_const_ALL:
  143.            LOG_REAL_PRINT_INET_in_AX_BX_DX_SI_const_ALL name
  144.             RET
  145.  
  146.             ;; 'internal' routines
  147.         log_print_str_in_CX_SI_DI_ES_out_DI_CX_const_BX_DX_BP_ES:
  148.            LOG_REAL_PRINT_STR_in_CX_SI_DI_ES_out_DI_CX_const_BX_DX_BP_ES name
  149.             RET
  150.         log_dec_ascii_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES:
  151.             LOG_REAL_DEC_ASCII_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES name
  152.             RET
  153.         log_hex_ascii_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES:
  154.             LOG_REAL_HEX_ASCII_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES name
  155.             RET
  156.         log_&name&_send_syslog_buff_in_CX:
  157.             LOG_REAL_SEND_SYSLOG_BUFF_in_CX name
  158.             RET
  159.         log_&name&_get_syslog_buff_in_DL_out_AX_DI_ES:
  160.             LOG_REAL_GET_SYSLOG_BUFF_in_DL_out_AX_DI_ES name
  161.             RET
  162.  
  163.         read_code:          ;; do nothing on syslog packet in
  164.             RET
  165.  
  166.         startup:            ;; issue a startup message
  167.             LOG_PRINT %mylog, L_SYS, L_INFO, <Starting up>
  168.             TIMER_RETURN %log_&name&_timer 
  169.  
  170.         timer_code:
  171.             ;; note that the timer is limited to 32K ticks
  172.         LOG_PRINT name, L_MON, L_NOTICE, <Router is up>
  173.         mov AX, 15*60*18            ;; go off every 15 min
  174.         cmp byte ptr log_&name&_data.log_pri, L_DEBUG+1
  175.         jbe time_ok
  176.             mov AX, 1*60*18         ;; go off every 1 min
  177.         time_ok:
  178.         TIMER_MARK_in_AX_const_CX_BP_ES %log_&name&_timer, timer_code
  179.         TIMER_RETURN %log_&name&_timer 
  180.     around:
  181.     log_&name&_define_in_AX_BX_SI:
  182.     mov log_&name&_data.log_pri , AX
  183.     mov log_&name&_data.log_mask, BX
  184.     lodsw                                   ;; save the admin host
  185.     mov word ptr log_&name&_data.log_host, AX
  186.     lodsw
  187.     mov word ptr log_&name&_data.log_host+2, AX
  188.  
  189.     UDP_SOCK_DEFINE %log_&name&_udp_sock, read_code
  190.  
  191.     test word ptr log_&name&_data.log_mask, (1 SHL L_MON)
  192.     jnz no_monitor
  193.         mov AX, 18*5
  194.         TIMER_MARK_in_AX_const_CX_BP_ES %log_&name&_timer, timer_code
  195.     no_monitor:
  196.  
  197.     mov AX, 0                       ;; send startup message
  198.     TIMER_MARK_in_AX_const_CX_BP_ES %log_&name&_timer, startup
  199.                                     ;; since the first one will be discarded
  200.                                     ;; since the arp cache is empty we send
  201.                                     ;; it again after it has been filled
  202.  
  203.     mov AX, 18*1                    ;; give it time to get an arp packet
  204.     TIMER_MARK_in_AX_const_CX_BP_ES %log_&name&_timer, startup
  205.     RET
  206. ENDM
  207.  
  208.  
  209. ;;**************************************************************************
  210. ;;   LOG_PRINT  name, type, severity, string
  211. ;;
  212. ;; LOG_PRINT logs the message 'string' to the syslogd with a serverity of
  213. ;;    'severity'.  a severity should be on of those defined above
  214. ;;    Note that this module violates convention and saves ALL registers
  215. ;;
  216. LOG_PRINT  MACRO name, type, severity, string
  217.    local mystring
  218.    .errb <string>
  219.  
  220.     .DATA
  221. mystring    db '&string', 0
  222.  
  223.    .CODE
  224.    push SI
  225.    push DX
  226.  
  227.    mov SI, offset mystring
  228.    mov DL, severity
  229.    mov DH, type
  230.    call log_&name&_print_in_DX_SI_const_ALL
  231.  
  232.    pop DX
  233.    pop SI
  234. ENDM
  235.  
  236.  
  237. ;;**************************************************************************
  238. ;;   LOG_PRINT_REG_HEX  name, type, severity, string, reg
  239. ;;
  240. ;; LOG_PRINT_REG_HEX logs the message 'string' to the syslogd with a serverity
  241. ;;    of 'severity'.  a severity should be on of those defined above
  242. ;;    Note that this module violates convention and saves ALL registers
  243. ;;    reg is then printed after the string in Hexidecimal notation
  244. ;;
  245. LOG_PRINT_REG_HEX  MACRO name, type, severity, string, reg
  246.    local mystring
  247.    .errb <string>
  248.  
  249.     .DATA
  250. mystring    db '&string', 0
  251.  
  252.    .CODE
  253.    push SI
  254.    push AX
  255.    push DX
  256.  
  257.    mov AX, reg
  258.    mov SI, offset mystring
  259.    mov DL, severity
  260.    mov DH, type
  261.    call log_&name&_print_hex_in_AX_DX_SI_const_ALL
  262.  
  263.    pop DX
  264.    pop AX
  265.    pop SI
  266. ENDM
  267.  
  268.  
  269. ;;**************************************************************************
  270. ;;   LOG_PRINT_REG_DEC  name, type, severity, string, reg
  271. ;;
  272. ;; LOG_PRINT_REG_DEC logs the message 'string' to the syslogd with a serverity
  273. ;;    of 'severity'.  a severity should be on of those defined above
  274. ;;    Note that this module violates convention and saves ALL registers
  275. ;;    reg is then printed after the string in Hexidecimal notation
  276. ;;
  277. LOG_PRINT_REG_DEC  MACRO name, type, severity, string, reg
  278.    local mystring
  279.    .errb <reg>
  280.  
  281.     .DATA
  282. mystring    db '&string', 0
  283.  
  284.    .CODE
  285.    push SI
  286.    push AX
  287.    push DX
  288.  
  289.    mov AX, reg
  290.    mov SI, offset mystring
  291.    mov DL, severity
  292.    mov DH, type
  293.    call log_&name&_print_dec_in_AX_DX_SI_const_ALL
  294.  
  295.    pop DX
  296.    pop AX
  297.    pop SI
  298. ENDM
  299.  
  300.  
  301. ;;**************************************************************************
  302. ;;   LOG_PRINT_INET_in_AX_BX  name, type, severity, string
  303. ;;
  304. ;; LOG_PRINT_INET_in_AX_BX logs the message 'string' to syslogd with a severity
  305. ;;    of 'severity'.  a severity should be on of those defined above
  306. ;;    Note that this module violates convention and saves ALL registers
  307. ;;    the register pair AX:BX is then printed in internet dot notation
  308. ;;
  309. LOG_PRINT_INET_in_AX_BX  MACRO name, type, severity, string
  310.    local mystring
  311.    .errb <string>
  312.  
  313.     .DATA
  314. mystring    db '&string', 0
  315.  
  316.    .CODE
  317.    push SI
  318.    push DX
  319.  
  320.    mov SI, offset mystring
  321.    mov DL, severity
  322.    mov DH, type
  323.    call log_&name&_print_inet_in_AX_BX_DX_SI_const_ALL
  324.  
  325.    pop DX
  326.    pop SI
  327. ENDM
  328.  
  329.  
  330. ;;**************************************************************************
  331. ;; Does the real work in doing printing
  332. ;;
  333. LOG_REAL_PRINT_in_DX_SI_const_ALL MACRO name
  334.     local done
  335.     .errb <name>
  336.  
  337.     push AX
  338.     push BX
  339.     push CX
  340.     push DX
  341.     push BP
  342.     push SI
  343.     push DI
  344.     push ES
  345.  
  346.     mov CL, DH          ;; should we log this
  347.     mov DI, 1
  348.     shl DI, CL
  349.     test DI, log_&name&_data.log_mask
  350.     jnz done
  351.     cmp DL, byte ptr log_&name&_data.log_pri
  352.     jae done
  353.  
  354.     push SI
  355.     call log_&name&_get_syslog_buff_in_DL_out_AX_DI_ES
  356.     pop SI
  357.     or AX, AX
  358.     jnz done
  359.  
  360.     xor CX, CX
  361.     call log_print_str_in_CX_SI_DI_ES_out_DI_CX_const_BX_DX_BP_ES
  362.     inc CX              ;; count the null terminator
  363.  
  364.     call log_&name&_send_syslog_buff_in_CX
  365.  
  366.     done:
  367.     pop ES
  368.     pop DI
  369.     pop SI
  370.     pop BP
  371.     pop DX
  372.     pop CX
  373.     pop BX
  374.     pop AX
  375. ENDM
  376.  
  377.  
  378. ;;**************************************************************************
  379. ;; Does the real work in doing printing a register in hex
  380. ;;
  381. LOG_REAL_PRINT_HEX_in_AX_DX_SI_const_ALL MACRO name
  382.     local done
  383.     .errb <name>
  384.  
  385.     push AX
  386.     push BX
  387.     push CX
  388.     push DX
  389.     push BP
  390.     push SI
  391.     push DI
  392.     push ES
  393.  
  394.     mov CL, DH          ;; should we log this
  395.     mov DI, 1
  396.     shl DI, CL
  397.     test DI, log_&name&_data.log_mask
  398.     jnz done
  399.     cmp DL, byte ptr log_&name&_data.log_pri
  400.     jae done
  401.  
  402.     push AX
  403.     push SI
  404.     call log_&name&_get_syslog_buff_in_DL_out_AX_DI_ES
  405.     pop SI
  406.     pop BX
  407.     or AX, AX
  408.     jnz done
  409.  
  410.     xor CX, CX
  411.     call log_print_str_in_CX_SI_DI_ES_out_DI_CX_const_BX_DX_BP_ES
  412.  
  413.     mov AX, BX
  414.     mov BP, DI 
  415.     mov DX, CX              ;; save CX
  416.     call log_hex_ascii_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES
  417.     mov CX, DX              ;; restore CX
  418.     sub BP, DI
  419.     sub CX, BP              ;; add in the length (negative of negative)
  420.  
  421.     mov AL, 0
  422.     stosb
  423.     inc CX              ;; count the null terminator
  424.  
  425.     call log_&name&_send_syslog_buff_in_CX
  426.     done:
  427.     pop ES
  428.     pop DI
  429.     pop SI
  430.     pop BP
  431.     pop DX
  432.     pop CX
  433.     pop BX
  434.     pop AX
  435. ENDM
  436.  
  437.  
  438. ;;**************************************************************************
  439. ;; Does the real work in doing printing a register in decimal
  440. ;;
  441. LOG_REAL_PRINT_DEC_in_AX_DX_SI_const_ALL MACRO name
  442.     local done
  443.     .errb <name>
  444.  
  445.     push AX
  446.     push BX
  447.     push CX
  448.     push DX
  449.     push BP
  450.     push SI
  451.     push DI
  452.     push ES
  453.  
  454.     mov CL, DH          ;; should we log this
  455.     mov DI, 1
  456.     shl DI, CL
  457.     test DI, log_&name&_data.log_mask
  458.     jnz done
  459.     cmp DL, byte ptr log_&name&_data.log_pri
  460.     jae done
  461.  
  462.     push AX
  463.     push SI
  464.     call log_&name&_get_syslog_buff_in_DL_out_AX_DI_ES
  465.     pop SI
  466.     pop BX
  467.  
  468.     or AX, AX
  469.     jnz done
  470.  
  471.     xor CX, CX
  472.     call log_print_str_in_CX_SI_DI_ES_out_DI_CX_const_BX_DX_BP_ES
  473.  
  474.     mov AX, BX
  475.     mov BP, DI 
  476.     mov DX, CX              ;; save CX
  477.     call log_dec_ascii_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES
  478.     mov CX, DX              ;; restore CX
  479.     sub BP, DI
  480.     sub CX, BP              ;; add in the length (negative of negative)
  481.  
  482.     mov AL, 0
  483.     stosb
  484.     inc CX              ;; count the null terminator
  485.  
  486.     call log_&name&_send_syslog_buff_in_CX
  487.     done:
  488.     pop ES
  489.     pop DI
  490.     pop SI
  491.     pop BP
  492.     pop DX
  493.     pop CX
  494.     pop BX
  495.     pop AX
  496. ENDM
  497.  
  498.  
  499. ;;**************************************************************************
  500. ;; Does the real work in doing printing an internet dot notation
  501. ;;
  502. LOG_REAL_PRINT_INET_in_AX_BX_DX_SI_const_ALL MACRO name
  503.     local done
  504.     .errb <name>
  505.  
  506.     push AX
  507.     push BX
  508.     push CX
  509.     push DX
  510.     push BP
  511.     push SI
  512.     push DI
  513.     push ES
  514.  
  515.     mov word ptr log_&name&_data.log_ip_addr, AX
  516.     mov word ptr log_&name&_data.log_ip_addr+2, BX
  517.  
  518.     mov CL, DH          ;; should we log this
  519.     mov BX, 1
  520.     shl BX, CL
  521.     test BX, log_&name&_data.log_mask
  522.     jnz done
  523.     cmp DL, byte ptr log_&name&_data.log_pri
  524.     jae done
  525.  
  526.     push SI
  527.     call log_&name&_get_syslog_buff_in_DL_out_AX_DI_ES
  528.     pop SI
  529.     or AX, AX
  530.     jnz done
  531.  
  532.     xor CX, CX
  533.     call log_print_str_in_CX_SI_DI_ES_out_DI_CX_const_BX_DX_BP_ES
  534.  
  535.     push CX             ;; save CX
  536.     push DI
  537.  
  538.     mov CX, 15          ;; maximum size of IP addr
  539.     mov AL, ' '
  540.     rep
  541.     stosb
  542.  
  543.     mov SI, offset log_&name&_data.log_ip_addr
  544.     IP_ASCII_in_SI_DI_ES_out_DI_const_BX_BP_ES 
  545.  
  546.     pop DI
  547.     pop CX              ;; restore CX
  548.  
  549.     add DI, 15          ;; size of IP address 
  550.     add CX, 15          ;; size of IP address 
  551.  
  552.     mov AL, 0
  553.     stosb
  554.     inc CX              ;; count the null terminator
  555.  
  556.     call log_&name&_send_syslog_buff_in_CX
  557.     done:
  558.     pop ES
  559.     pop DI
  560.     pop SI
  561.     pop BP
  562.     pop DX
  563.     pop CX
  564.     pop BX
  565.     pop AX
  566. ENDM
  567.  
  568.  
  569. ;;*************************************************************************
  570. ;; LOG_REAL_PRINT_STR_in_CX_SI_DI_ES_out_DI_CX_const_AX_BX_DX_BP_ES name
  571. ;;      copies the null terminated string in SI:DS to DI:ES, updates DI
  572. ;;      to point to the end of the new string.  CX is the present length
  573. ;;      of the output string and it is updated to the new length.
  574. ;;
  575. LOG_REAL_PRINT_STR_in_CX_SI_DI_ES_out_DI_CX_const_BX_DX_BP_ES MACRO name
  576.     local copy_loop, copy_loop_done, len_ok
  577.     .errb <name>
  578.  
  579.     copy_loop:
  580.         lodsb
  581.         stosb
  582.         inc CX
  583.  
  584.         cmp CX, 1000
  585.         jb len_ok
  586.             xor AL, AL
  587.             stosb
  588.             inc CX
  589.             jmp copy_loop_done
  590.         len_ok:
  591.         or AL, AL
  592.     jnz copy_loop
  593.     copy_loop_done:
  594.     dec CX                  ;; point to end of string
  595.     dec DI
  596. ENDM
  597.  
  598.  
  599. ;;*************************************************************************
  600. ;; LOG_REAL_SEND_SYSLOG_BUFF_in_CX sends the filled syslog buffer to 
  601. ;; the loging host. CX is the length of the messages.  CX MUST be less
  602. ;; than 256 (since syslog prints it all on one line, 80 is better)
  603. ;;
  604. LOG_REAL_SEND_SYSLOG_BUFF_in_CX MACRO name
  605.     .errb <name>
  606.  
  607.     add CX, 5
  608.     UDP_SOCK_W_WRITE_in_CX %log_&name&_udp_sock
  609. ENDM
  610.  
  611.  
  612. ;;*************************************************************************
  613. ;; LOG_REAL_GET_SYSLOG_BUFF_in_DL_out_AX_DI_ES gets a buffer for writing a 
  614. ;; Log message to the syslog host of priority 'DL' and returns it in DI:ES.  
  615. ;; If successful AX is zero
  616. ;;
  617. LOG_REAL_GET_SYSLOG_BUFF_in_DL_out_AX_DI_ES MACRO name
  618.     local done, get_buff
  619.     .errb <name>
  620.  
  621.     push DX                     ;; save the severity
  622.     mov CX, 256
  623.     mov DX, SYSLOG_PORT     
  624.     mov AX, word ptr log_&name&_data.log_host
  625.     mov BX, word ptr log_&name&_data.log_host+2
  626.     or AX, AX
  627.     jnz get_buff
  628.     or BX, BX
  629.     jnz get_buff
  630.         dec AX                 ;; make non-zero
  631.         pop DX
  632.         jmp done
  633.     get_buff:
  634.     UDP_SOCK_W_ACCESS_in_AX_BX_CX_DX_out_AX_DI_ES %log_&name&_udp_sock
  635.     pop DX
  636.     or AX, AX
  637.     jnz done
  638.  
  639.     mov AL, '<'
  640.     stosb
  641.  
  642.     mov AX, DX                  ;; AX = severity
  643.     xor AH, AH
  644.     add AX, log_&name&_facility*8
  645.     mov BL, 10
  646.     div BL                      ;; AL = AX / 10     AH = AX mod 10
  647.     mov BH, AH
  648.     xor AH, AH
  649.     div BL                      ;; AL = AX / 10     AH = AX mod 10
  650.     add AL, '0'
  651.     add AH, '0'
  652.     stosw
  653.     mov AL, BH
  654.     add AL, '0'
  655.     stosb
  656.     mov AL, '>'
  657.     stosb
  658.     xor AX, AX                  ;; success AX = 0
  659.     done:
  660. ENDM
  661.  
  662.  
  663. ;;*************************************************************************
  664. ;; LOG_REAL_HEX_ASCII_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES name
  665. ;;      This routine converts AX to Hex and puts the represenation in
  666. ;;      the buffer DI:ES.  DI points to the end of the buffer
  667. ;; 
  668. LOG_REAL_HEX_ASCII_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES MACRO name
  669.     local print_it, hex_loop
  670.     .errb <name>
  671.  
  672.     add DI, 3
  673.     std             ;; count down
  674.  
  675.     mov CX, 4
  676.     hex_loop:
  677.         mov SI, AX
  678.         shr SI, 1
  679.         shr SI, 1
  680.         shr SI, 1
  681.         shr SI, 1
  682.         and AL, 0FH
  683.  
  684.         add AL, '0'
  685.         cmp AL, '9'
  686.         jbe print_it
  687.             add AL, ('A' - '0' - 10)
  688.         print_it:
  689.         stosb
  690.         mov AX, SI
  691.     loop hex_loop
  692.     cld                 ;; count up again
  693.     add DI, 5           ;; make point to the end of the string
  694.  
  695.     mov AL, 'H'         ;; indicate that it is HEX
  696.     stosb
  697. ENDM
  698.  
  699.  
  700. ;;**************************************************************************
  701. ;; LOG_REAL_DEC_ASCII_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES name
  702. ;;      This routine converts AX to decimal and puts the represenation in
  703. ;;      the buffer DI:ES.  DI points to the end of the buffer
  704. ;; 
  705. LOG_REAL_DEC_ASCII_in_AX_DI_ES_out_DI_const_BX_DX_BP_ES MACRO name
  706.     local print_it, dec_loop
  707.     .errb <name>
  708.  
  709.     push DX
  710.     add DI, 4
  711.     std             ;; count down
  712.  
  713.     mov SI, 10
  714.     mov CX, 5
  715.     dec_loop:
  716.         xor DX, DX
  717.         idiv SI         ;; AX = AX / 10     DX = DX mod 10
  718.         xchg AX, DX
  719.         add AL, '0'
  720.         cmp AL, '0'
  721.         jnz print_it
  722.             cmp CX, 5
  723.             jz print_it
  724.             mov AL, ' '
  725.         print_it:
  726.         stosb
  727.         mov AX, DX
  728.     loop dec_loop
  729.     cld                 ;; count up again
  730.     add DI, 6           ;; make point to the end of the string
  731.     pop DX
  732. ENDM
  733.  
  734.