source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Libraries/print.asm @ 77

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

Minor size optimizations plus a bug fix in print.asm in Print_IntSW (DI was left hanging on the stack if the parameter in AX was positive). Also a very minor speed optimization in keys.asm in Keys_Backspace.

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