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

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