Video/Text modes
So to switch between video and text modes you need to use VGA BIOS:
mov ax,mode ; here select which mode you want
int 16 ; this calls EGA/VGA/VESA BIOS
There are many video modes here two very important ones:
mode | type | segment | resolution | align
----------------------------------------------------
03 | text | B800h | 80x25 chars | 2 Byte
19 | video | A000h | 320x200x256 colors | 1 Byte
In video mode 19
you print/peek pixel by accessing memory at segment A000h
where offset is computed like this:
offset = 320*y + x
The 320x200
mode fits entirely into 64 KByte
segment so you do not need to switch pages. This makes it ideal for simple asm gfx programs ....
Mode 3
is text mode where each character has 2 BYTEs
one is color and the other is extended ASCII code. Again print/peek is done by accessing WORD
at segment B800h
where offset is:
offset = (80*y + x) * 2
Not sure what order is the two bytes in anymore it was ages ago but you can easily test if writing A
at 0B800:0000
will render A
in top left corner or 0B800:0001
instead. IIRC colors in text modes are just first 16 colors from palette and the color byte encodes ink paper brightness and flash. This text mode is also the default mode your MS-DOS shell is working in so you should set it back before program exit.
So your program should look like this:
start:
mov ax,19 ; set video mode
int 16
mainloop:
; here your stuff
exit:
mov ax,3
int 16
ret
Printing strings
For starters you can combine text and video modes ... Like I do here:
it is a simple game where menus are in text mode (where printing is easy and just matter of copying the string into VRAM) and the sprite graphics game is on 320x200x256c
video mode.
When you want to print in gfx mode you first need to have some Font in the memory. If you look at the EGA/VGA BIOS documentation you can obtain the font located in EGA/VGA ROM and use directly that. I also created this image (IIRC using Trident 9000 256/512KB VGA font) which I use as a mono-spaced font for OpenGL and other stuff (where accessing VGA BIOS is not possible or wanted)...
Here GLSL example of using it for printing You can port it to CPU/VGA/asm but the printing on CPU is much more simpler no need for such horrible things like in GLSL fragment.
So you just need to compute image position from ASCII code and copy its pixels into VRAM. Of coarse having bitmap in asm is not easy and much easier is to have it directly in binary form (as set of db
) so you can write some simple C++ (or whatever) script which loads image and converts it to asm source ...
Here is some ancient 320x200x256 colors
printing lib I wrote in NASM ages ago (using EGA/VGA Font directly):
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;GFX mode 13h print librrary ver:1.0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;txti init font adress
;char cx=color,al=ASCII,scr:di<=al ;cl=ch => no background
;print scr:di <= ds:si ,cx=color cl=ch => no background
;printl scr:di text after call ,cx=color ...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
txti: pusha ;init font adress
push es
mov ax,1130h ; VGA BIOS - font info
mov bh,3 ; font 8 x 8 pixels
int 10h ; ES:BP returns font address
mov [cs:fonts],es ;get font adr
mov [cs:fonto],bp
pop es
popa
ret
fonts dw 0 ; font address for printing ...
fonto dw 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
char: pusha ;cx=color,al=ASCII,scr:di<=al ;cl=ch => no background
push ds
push es
push word 0A000h
pop es
sub ah,ah
shl ax,3
mov ds,[cs:fonts]
mov si,[cs:fonto]
add si,ax
mov dh,8
.char0: mov dl,8
lodsb
mov ah,al
.char1: mov al,cl
rcl ah,1
jc .char2
mov al,ch
.char2: cmp cl,ch
jz .char3
mov [es:di],al
.char3: inc di
dec dl
jnz .char1
add di,320-8
dec dh
jnz .char0
pop es
pop ds
popa
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print: pusha ;scr:di <= ds:si ,cx=color cl=ch => no background
.l0: lodsb
or al,al
jz .esc
call char
add di,8
jmp short .l0
.esc: popa
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printl: mov [cs:.dat],si ;scr:di text after call ,cx=color ...
pop si
push ax
push di
push ds
push cs
pop ds
.l0: lodsb
or al,al
jz .esc
call char
add di,8
jmp short .l0
.esc: pop ds
pop di
pop ax
push si
add di,9*320
mov si,[cs:.dat]
ret
.dat: dw 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; end. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
So to use it the program should be like:
start:
call txti ; just once at program startup
mov di,50+320*10
mov cx,127
call printl
db 'SPEKTRA software & hardware',0
mov di,50+320*30
mov cx,127
call printl
db 'print test',0
The print
is used by setting ds,si
so it points to your null terminated string. As you can see printl
does not need that as it uses string located directly after the printl
call and program continues after it ... This way you do not need pointer setting instructions nor any additional labes ... The colors are in cl,ch
one is ink and the other is paper. If cl==ch
then no paper will be rendered just the ink pixels that is useful if you got image or gfx background behind the text ... The values for colors might not be visible I taken the colors from one of mine games which sets its own palette so if nothing is visible try to set different cl,ch
like mov cx,0305h
Take a look at this:
nick
you have to add@nick
to the comment and site will do the rest – Adolphus