Statistics

Members: 1925
News: 293
Web Links: 1
Visitors: 3808553

Who's Online

We have 1 guest online
Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
Home arrow Articles - Programming arrow Assembly arrow VGA Programming in Mode 13h
VGA Programming in Mode 13h
User Rating: / 2
PoorBest 
Written by Lord Lucipher   


This article will describe how to program VGA graphics Mode 13h using assembly language. Mode 13h is the 320x200x256 graphics mode, and is fast and very convenient from a programmer's perspective. The video buffer begins at address A000:0000 and ends at address A000:F9FF. This means the buffer is 64000 bytes long and that each pixel in mode 13h is represented by one byte.

 

 

 

It is easy to set up mode 13h and the video buffer in assembly language:

        mov     ax,0013h        ; Int 10 - Video BIOS Services
int     10h             ; ah = 00 - Set Video Mode
; al = 13 - Mode 13h (320x200x256)
mov     ax,0A000h       ; point segment register es to A000h
mov     es,ax           ; we can now access the video buffer as
; offsets from register es

At the end of your program, you will probably want to restore the text mode. Here's how:

        mov     ax,0003h        ; Int 10 - Video BIOS Services
int     10h             ; ah = 00 - Set Video Mode
; al = 03 - Mode 03h (80x25x16 text)
Accessing a specific pixel int the buffer is also very easy:
; bx = x coordinate
; ax = y coordinate
mul     320             ; multiply y coord by 320 to get row
add     ax,bx           ; add this with the x coord to get offset
mov     cx,es:[ax]      ; now pixel x,y can be accessed as es:[ax]

Hmm... That was easy, but that multiplication is slow and we should get rid of it. That's easy to do too, simply by using bit shifting instead of multiplication. Shifting a number to the left is the same as multiplying by 2. We want to multiply by 320, which is not a multiple of 2, but 320 = 256 + 64, and 256 and 64 are both even multiples of 2. So a faster way to access a pixel is:

                                ; bx = x coordinate
; ax = y coordinate
mov     cx,bx           ; copy bx to cx, to save it temporatily
shl     cx,8            ; shift left by 8, which is the same as
; multiplying by 2^8 = 256
shl     bx,6            ; now shift left by 6, which is the same as
; multiplying by 2^6 = 64
add     bx,cx           ; now add those two together, whis is
; effectively multiplying by 320
add     ax,bx           ; finally add the x coord to this value
mov     cx,es:[ax]      ; now pixel x,y can be accessed as es:[ax]

Well, the code is a little bit longer and looks more complicated, but I can guarantee it's much faster.
To plot colors, we use a color look-up table. This look-up table is a 768 (3x256) array. Each index of the table is really the offset index*3. The 3 bytes at each index hold the corresponding values (0-63) of the red, green, and blue components. This gives a total of 262144 total possible colors. However, since the table is only 256 elements big, only 256 different colors are possible at a given time.
Changing the color palette is accomplished through the use of the I/O ports of the VGA card:

        Port 03C7h is the Palette Register Read port.
Port 03C8h is the Palette Register Write port
Port 03C9h is the Palette Data port
Here is how to change the color palette:
; ax = palette index
; bl = red component (0-63)
; cl = green component (0-63)
; dl = blue component (0-63)
mov     dx,03C8h        ; 03c8h = Palette Register Write port
out     dx,ax           ; choose index
mov     dx,03C9h        ; 03c8h = Palette Data port
out     dx,al
mov     bl,al           ; set red value
out     dx,al
mov     cl,al           ; set green value
out     dx,al
mov     dl,al           ; set blue value
Thats all there is to it.  Reading the color palette is similar:
; ax = palette index
; bl = red component (0-63)
; cl = green component (0-63)
; dl = blue component (0-63)
mov     dx,03C7h        ; 03c7h = Palette Register Read port
out     dx,ax           ; choose index
mov     dx,03C9h        ; 03c8h = Palette Data port
in      al,dx
mov     bl,al           ; get red value
in      al,dx
mov     cl,al           ; get green value
in      al,dx
mov     dl,al           ; get blue value

Now all we need to know is how to plot a pixel of a certain color at a certain location. Its very easy, given what we already know:

                                ; bx = x coordinate
; ax = y coordinate
; dx = color (0-255)
mov     cx,bx           ; copy bx to cx, to save it temporatily
shl     cx,8            ; shift left by 8, which is the same as
; multiplying by 2^8 = 256
shl     bx,6            ; now shift left by 6, which is the same as
; multiplying by 2^6 = 64
add     bx,cx           ; now add those two together, whis is
; effectively multiplying by 320
add     ax,bx           ; finally add the x coord to this value
mov     es:[ax],dx      ; copy color dx into memory location
; thats all there is to it

Ok, we now know how to set up Mode 13h, set up the video buffer, plot a pixel, and edit the color palette.
My next article will go on to show how to draw lines, utilize the vertical retrace for smoother rendering, and anything else I can figure out by that time...