source: xtideuniversalbios/trunk/Configurator/Src/Libraries/print.asm @ 181

Last change on this file since 181 was 181, checked in by krille_n_@…, 12 years ago

Changes to all parts of the project:

  • Size optimizations.
  • Added a define (EXCLUDE_FROM_XTIDECFG) to exclude unused library code from XTIDECFG.
  • Tried to minimize time spent with interrupts disabled.
  • Some minor attempts to improve speed (reordering instructions etc).
  • Tried to improve readability, did some cleanup and fixed some errors in comments.
File size: 18.8 KB
RevLine 
[2]1; Project name  :   Print library
[78]2; Description   :   ASM library for character and string
[2]3;                   printing related functions.
4
5;--------------- Equates -----------------------------
6
7; String library function to include
8%define USE_PRINT_FORMAT            ; Print_Format
9%define USE_PRINT_NEWLINE           ; Print_Newline
10%define USE_PRINT_CHARBUFFER        ; Print_CharBuffer
11%define USE_PRINT_REPEAT            ; Print_Repeat
12;%define USE_PRINT_BOOL             ; Print_Bool
13;%define USE_PRINT_INTSW            ; Print_IntSW
14%define USE_PRINT_INTUW             ; Print_IntUW
15;%define USE_PRINT_INTUDW           ; Print_IntUDW
16%define USE_PRINT_INTHEXB           ; Print_IntHexB
17%define USE_PRINT_INTHEXW           ; Print_IntHexW
18;%define USE_PRINT_INTHEXDW         ; Print_IntHexDW
19
20
21; Text mode character attribute byte bits for CGA+
22FLG_CGA_FG_B        EQU     (1<<0)
23FLG_CGA_FG_G        EQU     (1<<1)
24FLG_CGA_FG_R        EQU     (1<<2)
25FLG_CGA_FG_I        EQU     (1<<3)
26FLG_CGA_BG_B        EQU     (1<<4)
27FLG_CGA_BG_G        EQU     (1<<5)
28FLG_CGA_BG_R        EQU     (1<<6)
29FLG_CGA_BG_I        EQU     (1<<7)
30FLG_CGA_BG_BLNK     EQU     (1<<7)  ; Blinking is default
31
32; Text mode character attribute bytes for MDA/Hercules (mono)
33; *Not displayed on some monitors
34ATTR_MDA_HIDDEN     EQU     00h ; Not displayed
35ATTR_MDA_ULINE      EQU     01h ; Underlined
36ATTR_MDA_NORMAL     EQU     07h ; Normal (white on black)
37ATTR_MDA_INT_U      EQU     09h ; High intensity, underlined
38ATTR_MDA_INT        EQU     0Fh ; High intensity
39ATTR_MDA_REVERSE    EQU     70h ; Reverse video (black on white)
40ATTR_MDA_BLNK       EQU     87h ; Blinking white on black*
41ATTR_MDA_BLNK_INT   EQU     8Fh ; Blinking high intensity*
42ATTR_MDA_BLNK_REV   EQU     0F0h; Blinking reverse video
43
44
45;-------------- Private global variables -------------
46; Section containing initialized data
47;SECTION .data
48
49g_rgbHex:       db  "0123456789ABCDEF"  ; Hexadecimal printing
50g_rgbFormat:    ; Placeholders for Print_Format
51%ifdef USE_PRINT_INTSW
52                db  'd' ; Prints signed 16-bit integer (WORD)
53%endif
54%ifdef USE_PRINT_INTUW
55                db  'u' ; Prints unsigned 16-bit integer (WORD)
56%endif
57%ifdef USE_PRINT_INTUDW
58                db  'U' ; Prints unsigned 32-bit integer (DWORD)
59%endif
60%ifdef USE_PRINT_INTHEXW
61                db  'x' ; Prints 8- or 16-bit hexadecimal (BYTE, WORD)
62%endif
63%ifdef USE_PRINT_INTHEXDW
64                db  'X' ; Prints 32-bit hexadecimal (DWORD)
65%endif
66                db  's' ; Prints string (DS segment)
67                db  'S' ; Prints string (far pointer)
68%ifdef USE_PRINT_BOOL
69                db  'b' ; Prints boolean value 0 or 1
70%endif
71                db  'c' ; Prints character
72                db  'C' ; Prints character number of times
73_g_rgbFormatEnd:
74
75; Number of different placeholders for Print_Format
76CNT_PLCEHLDRS       EQU     (_g_rgbFormatEnd-g_rgbFormat)
77
78
79
80;-------------- Public functions ---------------------
81; Section containing code
82SECTION .text
83
84; Include one file to use DOS, BIOS or VRAM macros and functions
85;%include "prntdos.asm"         ; Include to use DOS printing functions
86%include "prntbios.asm"         ; Include to use BIOS printing functions
87;%include "prntvram.asm"            ; Include to access VRAM directly
88
89
90;--------------------------------------------------------------------
91; Debugging macro that prints wanted character and newline.
[181]92;
[2]93; PRINT_DBG_CH
94;   Parameters:
95;       %1:     Character to print
96;   Returns:
97;       Nothing
98;   Corrupts registers:
99;       Nothing
100;--------------------------------------------------------------------
101%macro PRINT_DBG_CH 1
102    pushf
103    push    dx
104    push    ax
105    mov     dl, %1
106    PRINT_CHAR
[78]107    ;mov        dl, CR
108    ;PRINT_CHAR
109    ;mov        dl, LF
110    ;PRINT_CHAR
[2]111    pop     ax
112    pop     dx
113    popf
114%endmacro
115
116
117;--------------------------------------------------------------------
118; Simplified printf-style string formatting function.
119; Strings must end to STOP character.
120; Supports following formatting types:
121;   %d      Prints signed 16-bit integer (WORD)
122;   %u      Prints unsigned 16-bit integer (WORD)
123;   %U      Prints unsigned 32-bit integer (DWORD)
124;   %x      Prints 8- or 16-bit hexadecimal (BYTE, WORD)
125;   %X      Prints 32-bit hexadecimal (DWORD)
126;   %s      Prints string (DS segment)
127;   %S      Prints string (far pointer)
128;   %b      Prints boolean value 0 or 1
129;   %c      Prints character
130;   %[num]C Prints character number of times (up to 256, 0=256)
131;   %%      Prints '%' character (no parameter pushed)
132;
133;   Any placeholder can be set to minimum length by specifying
134;   minimum number of characters. For example %8d would append spaces
135;   after integer so that at least 8 characters would be printed.
136;
137;   NOTE! Caller must clean the stack variables!
[181]138;
[2]139; Print_Format
140;   Parameters:
141;       DL:         Min length character (usually space)
142;       DS:SI:      Pointer to string to format
143;       Stack:      Parameters for formatting placeholders.
144;                   Parameter for first placeholder must be pushed last
145;                   (to top of stack).
146;                   High word must be pushed first for 32-bit parameters.
147;   Returns:
148;       Nothing
149;   Corrupts registers:
150;       AX, SI
151;--------------------------------------------------------------------
152%ifdef USE_PRINT_FORMAT
153ALIGN JUMP_ALIGN
154Print_Format:
155    push    es
156    push    bp
157    push    di
158    push    cx
159    push    dx                  ; Push min length character
160    push    cs                  ; Copy CS...
161    pop     es                  ; ...to ES
162    mov     bp, sp              ; Copy SP to BP
163    add     bp, 2*6             ; Set BP to point first stack parameter
164    cld                         ; Set LODSB to increment SI
165ALIGN JUMP_ALIGN
166.PrintLoop:         ; Load characters from string
167    lodsb                       ; Load char from DS:SI to AL, increment SI
168    xor     cx, cx              ; Zero minimum length
169    cmp     al, STOP            ; End of string?
170    je      .Return             ;  If so, return
171    cmp     al, '%'             ; Format placeholder?
172    je      .Format             ;  If so, jump to format
173ALIGN JUMP_ALIGN
174.PrintChar:         ; Prints single character from AL
175    mov     dl, al              ; Copy character to DL
176    PRINT_CHAR                  ; Print character
177    mov     dx, 1               ; One char printed
178ALIGN JUMP_ALIGN
179.PrintXtraSoMin:    ; Checks how many spaces to append
180    sub     cx, dx              ; Number of spaces needed
181    jle     .PrintLoop          ; Read next character if no spaces needed
182    pop     dx                  ; Pop min length character to DL
183ALIGN JUMP_ALIGN
184.PrintSpaceLoop:    ; Loop to print the required spaces
185    PRINT_CHAR
186    loop    .PrintSpaceLoop
187    push    dx                  ; Store min length character
188    jmp     .PrintLoop          ; Jump to read next character
189ALIGN JUMP_ALIGN
190.Return:            ; The only return point for this function
191    pop     dx
192    pop     cx
193    pop     di
194    pop     bp
195    pop     es
196    ret
197ALIGN JUMP_ALIGN
198.UpdateMinLen:      ; Updates placeholder minimum length
199    mov     al, ah              ; Copy digit to AL
200    mov     ah, cl              ; Copy previous length to AH
201    aad                         ; AL=10*AH+AL, AH=0
202    mov     cx, ax              ; Copy new length to CX
203ALIGN JUMP_ALIGN
204.Format:
205    lodsb                       ; Load char from DS:SI to AL, increment SI
206    cmp     al, STOP
207    je      .Return             ; Invalid string
208    mov     ah, al              ; Copy char to AH
209    sub     ah, '0'             ; Possible digit char to digit
210    cmp     ah, 9               ; Was valid digit?
211    jbe     .UpdateMinLen       ;  If so, jump to update minimum length
212    push    cx                  ; Store number of spaces needed
213    mov     cx, CNT_PLCEHLDRS   ; Load number of placeholders to CX
214    mov     di, g_rgbFormat     ; Load offset to format placeholder table
215    repne scasb                 ; Compare AL to [ES:DI] until match
216    pop     cx                  ; Restore spaces needed
217    jne     .PrintChar          ; If no match, jump to print character
218    sub     di, g_rgbFormat+1   ; To placeholder index
219    shl     di, 1               ; Shift for word lookup
220    jmp     [cs:di+.g_rgwFormJump]  ; Jump to format
221
222%ifdef USE_PRINT_INTSW
223ALIGN JUMP_ALIGN
224.Print_d:   ; Print signed 16-bit integer
225    mov     ax, [bp]            ; Load word to print
226    times 2 inc bp
227    call    Print_IntSW
228    jmp     .PrintXtraSoMin
229%endif
230%ifdef USE_PRINT_INTUW
231ALIGN JUMP_ALIGN
232.Print_u:   ; Print unsigned 16-bit integer
233    mov     ax, [bp]            ; Load word to print
234    times 2 inc bp
235    call    Print_IntUW
236    jmp     .PrintXtraSoMin
237%endif
238%ifdef USE_PRINT_INTUDW
239ALIGN JUMP_ALIGN
240.Print_U:   ; Print unsigned 32-bit integer
241    mov     ax, [bp]            ; Load loword
242    mov     dx, [bp+2]          ; Load hiword
243    add     bp, 4
244    call    Print_IntUDW
245    jmp     .PrintXtraSoMin
246%endif
247%ifdef USE_PRINT_INTHEXW
248ALIGN JUMP_ALIGN
249.Print_x:   ; Prints 8- or 16-bit hexadecimal
250    mov     ax, [bp]            ; Load word to print
251    times 2 inc bp
252%ifdef USE_PRINT_INTHEXB
253    test    ah, ah              ; 16-bit hexadecimal?
254    jnz     .Print_x16          ;  If so, jump to print it
255    call    Print_IntHexB
256    jmp     .PrintXtraSoMin
257.Print_x16:
258%endif
259    call    Print_IntHexW
260    jmp     .PrintXtraSoMin
261%endif
262%ifdef USE_PRINT_INTHEXDW
263ALIGN JUMP_ALIGN
264.Print_X:   ; Prints 32-bit hexadecimal
265    mov     ax, [bp]            ; Load loword
266    mov     dx, [bp+2]          ; Load hiword
267    add     bp, 4
268    call    Print_IntHexDW
269    jmp     .PrintXtraSoMin
270%endif
271ALIGN JUMP_ALIGN
272.Print_s:   ; Prints string from DS segment
273    mov     dx, [bp]            ; Load offset to string
274    times 2 inc bp
275    PRINT_STR_LEN               ; Print string
276    jmp     .PrintXtraSoMin
277ALIGN JUMP_ALIGN
278.Print_S:   ; Prints string using far pointer
279    push    ds                  ; Store DS
280    mov     dx, [bp]            ; Load offset to string
281    mov     ds, [bp+2]          ; Load segment to string
282    add     bp, 4
283    PRINT_STR_LEN               ; Print string
284    pop     ds                  ; Restore DS
285    jmp     .PrintXtraSoMin
286%ifdef USE_PRINT_BOOL
287ALIGN JUMP_ALIGN
288.Print_b:   ; Prints boolean value
289    mov     ax, [bp]            ; Load boolean value to print
290    times 2 inc bp
291    call    Print_Bool
292    jmp     .PrintXtraSoMin
293%endif
294ALIGN JUMP_ALIGN
295.Print_c:   ; Prints character
296    mov     ax, [bp]            ; Load character to print
297    times 2 inc bp
298    jmp     .PrintChar          ; Jump to print character
299ALIGN JUMP_ALIGN
300.Print_C:
301    mov     dx, [bp]            ; Load character to print
302    times 2 inc bp
303ALIGN JUMP_ALIGN
304.CharLoop:
305    PRINT_CHAR
306    loop    .CharLoop
307    jmp     .PrintLoop
308
309ALIGN JUMP_ALIGN
310.g_rgwFormJump:                 ; Jump table for Print_Format
311%ifdef USE_PRINT_INTSW
312    dw      .Print_d
313%endif
314%ifdef USE_PRINT_INTUW
315    dw      .Print_u
316%endif
317%ifdef USE_PRINT_INTUDW
318    dw      .Print_U
319%endif
320%ifdef USE_PRINT_INTHEXW
321    dw      .Print_x
322%endif
323%ifdef USE_PRINT_INTHEXDW
324    dw      .Print_X
325%endif
326    dw      .Print_s
327    dw      .Print_S
328%ifdef USE_PRINT_BOOL
329    dw      .Print_b
330%endif
331    dw      .Print_c
332    dw      .Print_C
333%endif
334
335
336;--------------------------------------------------------------------
337; Prints newline character to change line.
[181]338;
[2]339; Print_Newline
340;   Parameters:
341;       Nothing
342;   Returns:
343;       Nothing
344;   Corrupts registers:
345;       Nothing
346;--------------------------------------------------------------------
347%ifdef USE_PRINT_NEWLINE
348ALIGN JUMP_ALIGN
349Print_Newline:
350    push    ax
351    push    dx
352    mov     dl, LF
353    PRINT_CHAR
354    mov     dl, CR
355    PRINT_CHAR
356    pop     dx
357    pop     ax
358    ret
359%endif
360
[181]361
[2]362;--------------------------------------------------------------------
363; Prints wanted number of characters.
[181]364;
[2]365; Print_CharBuffer
366;   Parameters:
367;       CX:     Number of characters to print
368;       ES:DI:  Ptr to character buffer
369;   Returns:
370;       Nothing
371;   Corrupts registers:
372;       AX, CX
373;--------------------------------------------------------------------
374%ifdef USE_PRINT_CHARBUFFER
375ALIGN JUMP_ALIGN
376Print_CharBuffer:
377    jcxz    .Return
378    push    ds
379    push    si
380    push    dx
381    push    es
382    pop     ds
383    mov     si, di
384    cld                         ; LODSB to increment SI
385ALIGN JUMP_ALIGN
386.Rep:
387    lodsb                       ; Load from [DS:SI] to AL
388    mov     dl, al              ; Copy to DL for printing
389    PRINT_CHAR
390    loop    .Rep
391    pop     dx
392    pop     si
393    pop     ds
394.Return:
395    ret
396%endif
397
398
399;--------------------------------------------------------------------
400; Repeats wanted character.
[181]401;
[2]402; Print_Repeat
403;   Parameters:
404;       CX:     Number of times to repeat character
405;       DL:     Character to repeat
406;   Returns:
407;       Nothing
408;   Corrupts registers:
409;       AX, CX
410;--------------------------------------------------------------------
411%ifdef USE_PRINT_REPEAT
412ALIGN JUMP_ALIGN
413Print_Repeat:
414    jcxz    .Return
415ALIGN JUMP_ALIGN
416.Rep:
417    PRINT_CHAR
418    loop    .Rep
419.Return:
420    ret
421%endif
422
423
424;--------------------------------------------------------------------
425; Prints boolean value.
[181]426;
[2]427; Print_Bool
428;   Parameters:
429;       AX:     Boolean value (0=FALSE, non-zero=TRUE)
430;   Returns:
431;       DX:     Number of characters printed
432;   Corrupts registers:
433;       AX
434;--------------------------------------------------------------------
435%ifdef USE_PRINT_BOOL
436ALIGN JUMP_ALIGN
437Print_Bool:
438    mov     dl, '0'             ; Assume FALSE
439    test    ax, ax              ; Is FALSE?
440    jz      .Print              ;  If so, jump to print
441    inc     dx                  ; Increment to '1'
442ALIGN JUMP_ALIGN
443.Print:
444    PRINT_CHAR
445    mov     dx, 1               ; One character printed
446    ret
447%endif
448
449
450;--------------------------------------------------------------------
451; Prints signed or unsigned 16-bit integer.
[181]452;
[2]453; Print_IntSW   Prints signed 16-bit word
454; Print_IntUW   Prints unsigned 16-bit word
455;   Parameters:
456;       AX:     Word to print
457;   Returns:
458;       DX:     Number of characters printed
459;   Corrupts registers:
460;       AX
461;--------------------------------------------------------------------
462%ifdef USE_PRINT_INTSW
463ALIGN JUMP_ALIGN
464Print_IntSW:
[78]465    test    ax, ax              ; Positive integer?
466    jns     Print_IntUW         ;  If so, jump to print it
[2]467    push    di                  ; Store DI
468    push    ax                  ; Store word
469    mov     dl, '-'             ; Print '-'
470    PRINT_CHAR
471    mov     di, 1               ; One character printed
472    pop     ax                  ; Restore word
473    neg     ax                  ; Negative to positive
474    jmp     Print_ContinueFromIntSW
475%endif
476
477%ifdef USE_PRINT_INTUW or USE_PRINT_INTSW
478ALIGN JUMP_ALIGN
479Print_IntUW:
480    push    di                  ; Store DI
481    xor     di, di              ; Zero character counter
482Print_ContinueFromIntSW:
483    push    bx                  ; Store BX
484    push    cx                  ; Store CX
485    mov     bx, 10              ; Load divisor to BX
486    mov     cx, 5               ; Load number of divisions to CX
487ALIGN JUMP_ALIGN
488.DivLoop:
489    xor     dx, dx              ; Zero DX for division
490    div     bx                  ; DX:AX / 10 => AX=quot, DX=rem
491    push    dx                  ; Push digit
492    loop    .DivLoop            ; Loop to separate all characters
493    xor     bx, bx              ; First char printed flag
494    mov     cl, 5               ; Load number of characters to CL
495ALIGN JUMP_ALIGN
496.PrintLoop:
497    pop     dx                  ; Pop character to DX
498    or      bx, dx              ; Still skipping zeroes?
499    loopz   .PrintLoop          ;  If so, loop
500    add     dx, '0'             ; Digit to character
501    PRINT_CHAR                  ; Print character
502    inc     di                  ; Increment chars printed
[181]503    inc     cx                  ; Characters left
504    loop    .PrintLoop          ;  If so, loop
[2]505    mov     dx, di              ; Copy chars printed to DX
506    pop     cx
507    pop     bx
508    pop     di
509    ret
510%endif
511
512
513;--------------------------------------------------------------------
514; Prints unsigned 32-bit integer.
[181]515;
[2]516; Print_IntUDW
517;   Parameters:
518;       DX:AX:  32-bit unsigned integer to print
519;   Returns:
520;       DX:     Number of characters printed
521;   Corrupts registers:
522;       AX
523;--------------------------------------------------------------------
524%ifdef USE_PRINT_INTUDW
525ALIGN JUMP_ALIGN
526Print_IntUDW:
527    push    di                  ; Store DI
528    push    si                  ; Store SI
529    push    bx                  ; Store BX
530    push    cx                  ; Store CX
531    mov     cx, 10              ; Load divider to CX
532    mov     si, cx              ; Load number of divisions (10) to SI
533    xor     di, di              ; Zero DI (char counter)
534ALIGN JUMP_ALIGN
535.DivLoop:
536    call    Math_DivDWbyW       ; DX:AX / 10 => DX:AX=quot, BX=rem
537    push    bx                  ; Push digit
538    dec     si                  ; Decrement number of divisions
539    jnz     .DivLoop            ;  Loop while divisions left
540    xor     bx, bx              ; First char printed flag
541ALIGN JUMP_ALIGN
542.PrintLoop:
543    pop     dx                  ; Pop character to DX
544    or      bx, dx              ; Still skipping zeroes?
545    loopz   .PrintLoop          ;  If so, loop
546    add     dx, '0'             ; Digit to character
547    PRINT_CHAR                  ; Print character
548    inc     di                  ; Increment chars printed
[181]549    inc     cx                  ; Characters left
550    loop    .PrintLoop          ;  If so, loop
[2]551    mov     dx, di              ; Copy characters printed to DX
552    pop     cx
553    pop     bx
554    pop     si
555    pop     di
556    ret
557%endif
558
559
560;--------------------------------------------------------------------
561; Prints 8-bit byte as hexadecimal string.
[181]562;
[2]563; Print_IntHexB
564;   Parameters:
565;       AL:     8-bit BYTE to print
566;   Returns:
567;       DX:     Number of characters printed
568;   Corrupts registers:
569;       AX
570;--------------------------------------------------------------------
571%ifdef USE_PRINT_INTHEXB
572ALIGN JUMP_ALIGN
573Print_IntHexB:
574    push    bx
575    xor     ah, ah              ; Zero AH, AX=word to print
576    mov     bx, 0FFh            ; Set to print two digits
577    call    Print_HexString     ; Print hex string
578    push    dx                  ; Store number of chars printed
579    mov     dl, 'h'             ; Print 'h' at the end
580    PRINT_CHAR
581    pop     dx                  ; Restore number of chars printed
582    inc     dx                  ; Increment for 'h'
583    pop     bx
584    ret
585%endif
586
587
588;--------------------------------------------------------------------
589; Prints 16-bit word as hexadecimal string.
[181]590;
[2]591; Print_IntHexW
592;   Parameters:
593;       AX:     16-bit WORD to print
594;   Returns:
595;       DX:     Number of characters printed
596;   Corrupts registers:
597;       AX
598;--------------------------------------------------------------------
599%ifdef USE_PRINT_INTHEXW
600ALIGN JUMP_ALIGN
601Print_IntHexW:
602    push    bx
603    xor     bx, bx              ; Set to print all zeroes...
604    dec     bx                  ; ...BX = FFFFh
605    call    Print_HexString     ; Print hex string
606    push    dx                  ; Store number of chars printed
607    mov     dl, 'h'             ; Print 'h' at the end
608    PRINT_CHAR
609    pop     dx                  ; Restore number of chars printed
610    inc     dx                  ; Increment for 'h'
611    pop     bx
612    ret
613%endif
614
615
616;--------------------------------------------------------------------
617; Prints 32-bit dword as hexadecimal string.
[181]618;
[2]619; Print_IntHexDW
620;   Parameters:
621;       DX:AX:  32-bit DWORD to print
622;   Returns:
623;       DX:     Number of characters printed
624;   Corrupts registers:
625;       AX
626;--------------------------------------------------------------------
627%ifdef USE_PRINT_INTHEXDW
628ALIGN JUMP_ALIGN
629Print_IntHexDW:
630    push    cx
631    push    bx
632    push    ax                  ; Store loword
633    mov     ax, dx              ; Copy hiword to AX
634    xor     bx, bx              ; Set to print all zeroes...
635    dec     bx                  ; ...BX = FFFFh
636    call    Print_HexString     ; Print hex string
637    mov     cx, dx              ; Copy number of chars printed
638    pop     ax                  ; Pop loword
639    call    Print_HexString     ; Print hex string
640    add     cx, dx              ; Add number of chars printed
641    mov     dl, 'h'             ; Print 'h' at the end
642    PRINT_CHAR
643    inc     cx                  ; Increment number of chars printed
644    mov     dx, cx              ; Copy number of chars printed to DX
645    pop     bx
646    pop     cx
647    ret
648%endif
649
650
651;-------------- Private functions --------------------
652
653;--------------------------------------------------------------------
654; Prints hexadecimal character for every nybble for WORD.
[181]655;
[2]656; Print_HexString
657;   Parameters:
658;       AX:     16-bit WORD to print
659;       BX:     Mask for zero nybbles to print:
660;               FFFFh   = prints all digits
661;               0FFFh   = does not print digit 3 if it is zero
662;               00FFh   = does not print digits 3 and 2 if both are zeroes
663;               000Fh   = prints only digit 0 if other are zeroes
664;               0000h   = prints nothing if value is zero
665;   Returns:
666;       DX:     Number of characters printed
667;   Corrupts registers:
668;       AX
669;--------------------------------------------------------------------
670%ifdef USE_PRINT_INTHEXB or USE_PRINT_INTHEXW or USE_PRINT_INTHEXDW
671ALIGN JUMP_ALIGN
672Print_HexString:
673    push    bp
674    push    di
675    push    si
676    push    cx
677
678    mov     di, ax              ; Backup WORD to DI
679    mov     cl, 12              ; Prepare to shift nybbles
680    xor     dx, dx              ; Zero DX
681ALIGN JUMP_ALIGN
682.NybbleLoop:
683    mov     bp, bx              ; Copy mask to BP
684    mov     si, di              ; Copy WORD to SI
685    shr     bp, cl              ; Shift wanted mask nybble to BP
686    shr     si, cl              ; Shift wanted nybble to SI
687    and     bp, 0Fh             ; Clear unwanted mask bits
688    and     si, 0Fh             ; Clear unwanted bits
689    or      bp, si              ; Skip zeroes in front?
690    jz      .SkipPrint          ;  If so, skip printing
691    mov     dl, [cs:si+g_rgbHex]; Load char to DL
692    PRINT_CHAR                  ; Print character
693    inc     dh                  ; Increment characters printed
694.SkipPrint:
695    sub     cl, 4               ; Prepare to shift next nybble
696    jnc     .NybbleLoop         ; Loop while nybbles left
697    mov     dl, dh              ; Copy chars printed to DL
698    xor     dh, dh              ; Zero DH
699
700    pop     cx
701    pop     si
702    pop     di
703    pop     bp
704    ret
705%endif
Note: See TracBrowser for help on using the repository browser.