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