This next example demonstrates how to write to the screen using the file function 40h of interrupt 21h.Listing 12: TEXT1.ASM .model tiny .code org 100h start: mov dh,12 ; cursor col mov dl,32 ; cursor row mov ah,02h ; move cursor to the right place xor bh,bh ; video page 0 int 10h ; call bios service mov dx,OFFSET Text ; DS:DX points to message mov ah,9 ; function 9 - display string int 21h ; all dos service mov ax,4C00h ; exit to dos int 21h Text DB "This is some text$" end start
The next program shows how to set up and call function 13h of interrupt 10h - write string. This has the advantages of being able to write a string anywhere on the screen in a specified colour but it is hard to set up.Listing 13: TEXT2.ASM .model small .stack .code mov ax,@data ; set up ds as the segment for data mov ds,ax mov ah,40h ; function 40h - write file mov bx,1 ; handle = 1 (screen) mov cx,17 ; length of string mov dx,OFFSET Text ; DS:DX points to string int 21h ; call DOS service mov ax,4C00h ; terminate program int 21h .data Text DB "This is some text" end
The next program demonstrates how to write to the screen using rep stosw to put the writing in video memory.Listing 14: TEXT3.ASM .model small .stack .code mov ax,@data ; set up ds as the segment for data mov es,ax ; put this in es mov bp,OFFSET Text ; ES:BP points to message mov ah,13h ; function 13 - write string mov al,01h ; attrib in bl,move cursor xor bh,bh ; video page 0 mov bl,5 ; attribute - magenta mov cx,17 ; length of string mov dh,5 ; row to put string mov dl,5 ; column to put string int 10h ; call BIOS service mov ax,4C00h ; return to DOS int 21h .data Text DB "This is some text" end
The next program demonstrates how to write a string to video memory.Listing 15: TEXT4.ASM .model small .stack .code mov ax,0B800h ; segment of video buffer mov es,ax ; put this into es xor di,di ; clear di, ES:DI points to video memory mov ah,4 ; attribute - red mov al,"G" ; character to put there mov cx,4000 ; amount of times to put it there cld ; direction - forwards rep stosw ; output character at ES:[DI] mov ax,4C00h ; return to DOS int 21h end
It is left as an exercise to the reader to modify it so that only one write is made to video memory.Listing 15: DIRECTWR.ASM ; write a string direct to video memory .model small .stack .code mov ax,@data mov ds,ax mov ax,0B800h ; segment of video buffer mov es,ax ; put this into es mov ah,3 ; attribute - cyan mov cx,17 ; length of string to print mov si,OFFSET Text ; DX:SI points to string xor di,di Wr_Char: lodsb ; put next character into al mov es:[di],al ; output character to video memory inc di ; move along to next column mov es:[di],ah ; output attribute to video memory inc di loop Wr_Char ; loop until done mov ax,4C00h ; return to DOS int 21h .data Text DB "This is some text" end
Just use this to check if mode 13h is supported at the beginning of your program to make sure that you can go into that mode.Listing 16: CHECK13.ASM .model small .stack .data NoSupport db "Mode 13h is not supported on this computer." db ,"You need either a MCGA or VGA video" db ,"card/monitor.$" Supported db "Mode 13h is supported on this computer.$" .code mov ax,@data ; set up DS to point to data segment mov ds,ax ; use ax call Check_Mode_13h ; check if mode 13h is possible jc Error ; if cf=1 there is an error mov ah,9 ; function 9 - display string mov dx,OFFSET Supported ; DS:DX points to message int 21h ; call DOS service jmp To_DOS ; exit to DOS Error: mov ah,9 ; function 9 - display string mov dx,OFFSET NoSupport ; DS:DX points to message int 21h ; call DOS service To_DOS: mov ax,4C00h ; exit to DOS int 21h Check_Mode_13h PROC ; Returns: CF = 1 Mode 13h not possible mov ax,1A00h ; Request video info for VGA int 10h ; Get Display Combination Code cmp al,1Ah ; Is VGA or MCGA present? je Mode_13h_OK ; mode 13h is supported stc ; mode 13h isn't supported CF=1 Mode_13h_OK: ret Check_Mode_13h ENDP end
Once we are in mode 13h and have finished what we are doing we need to we need to set it to the video mode that it was in previously.mov ax,13h ; set mode 13h int 10h ; call BIOS service
This is done in two stages. Firstly we need to save the video mode and then reset it to that mode.
Now that we can get into mode 13h lets do something. Firstly lets put some pixels on the screen.VideoMode db ? . . mov ah,0Fh ; function 0Fh - get current mode int 10h ; Bios video service call mov VideoMode,al ; save current mode ; program code here mov al,VideoMode ; set previous video mode xor ah,ah ; clear ah - set mode int 10h ; call bios service mov ax,4C00h ; exit to dos int 21h ; call dos function
Function 0Ch: Write Graphics Pixel
This makes a colour dot on the screen at the specified graphics coordinates.
AH = 0Ch
AL = Color of the dot
CX = Screen column (x coordinate)
DX = Screen row (y coordinate)
Nothing except pixel on screen.
Note: This function performs exclusive OR (XOR) with the new colour value and the current context of the pixel of bit 7 of AL is set.
This program demonstrates how to plot pixels. It should plot four red pixels into the middle of the screen.
Listing 17: PIXINT.ASM ; example of plotting pixels in mode 13 using bios services - ; INT 10h .model tiny .code org 100h start: mov ax,13 ; mode = 13h int 10h ; call bios service mov ah,0Ch ; function 0Ch mov al,4 ; color 4 - red mov cx,160 ; x position = 160 mov dx,100 ; y position = 100 int 10h ; call BIOS service inc dx ; plot pixel downwards int 10h ; call BIOS service inc cx ; plot pixel to right int 10h ; call BIOS service dec dx ; plot pixel up int 10h ; call BIOS service xor ax,ax ; function 00h - get a key int 16h ; call BIOS service mov ax,3 ; mode = 3 int 10h ; call BIOS service mov ax,4C00h ; exit to DOS int 21h end start
The VGA segment is 0A000h. To work out where each pixel goes you use this simple formula to get the offset.
Offset = X + ( Y * 320 )
All we do is to put a number at this location and there is now a pixel on the screen. The number is what colour it is. There are two instructions that we can use to put a pixel on the screen, firstly we could use stosb to put the value in AL to ES:DI or we can use a new form of the MOV instruction like this:
Which should we use? When we are going to write pixels to the screen we need to do so as fast as it is possible.mov es:[di], color
Instruction Pentium 486 386 286 86 STOSB 3 5 4 3 11 MOV AL to SEG:OFF 1 1 4 3 10If you use the MOV method you may need to increment DI (which STOSB does).
If we had a program which used sprites which need to be continuously draw, erased and then redraw you will have problems with flicker. To avoid this you can use a 'double buffer'. This is another part of memory which you write to and then copy all the information onto thescreen.