╖ Demo coding - the basics ╖

© 1998 by Cruehead / MiB


Hiya there!

Here comes some info on how to get started with democoding. What we will deal with in ths essay is setting up a VGA screen and drawing a pixel on the screen (ok - I know it doesnt sound to interesting but hang in there - the cool parts will come later :)). We'll also talk about optimizing.


Ok, lets start out with mode 13h. What's mode 13h? It's the graphic mode most demos and games are (or were, nowadays windows has taken more control of that part) written in. Mode 13h has a size of 320*200 pixels where every pixel can have any of 256 colors. As you might know from mode 3
(= textmode - the one that you usually use), the segment address of the screen memory is 08b00h. This is not true for mode 13h! Here the screen memory begins at the segment address 0a000h.
Ok - let's say that you want to draw a pixel to the screen, what do you need?

1 - Segment address of the screen memory (you already got this - 0a000h remember?)
2 - Offset (ie where on the screen you want to write)
3 - Color of the pixel

We know the first part, so let's jump to the offset...how do we calculate it? You should be able to figure out that yourself knowing the screen limits, but ok - I'll help you with it.

Offset = 320*y + x.

where ofcourse X and Y are coordinates. If we want to write to the first position of the screen (0,0 - in the upper left corner) we put these values in our formula. 320*0+0 = 0. So, the offset for this position is 0. So far so good, let's try to calculate the offset for (5,10). Offset = 320*10 + 5 = 3205. You see - it isnt very complicated...now you should understand how the offset calculations work so we can jump to...

...Color of the pixel...not much to say about it - just specify a value between 0-255 and sent it to the screen...let's go to the interesting part instead - lets see some asm code!



;Setup VGA and write to it

mov	ax,013h			;This is how we change the graphic mode
int	10h

mov	ax,0a000h		;Lets use es (extra segment register) as our screen segment
mov	es,ax			;We cant type "mov es,0a000h"
mov 	di,offs			;We'll use di (destination index) as our offset.
mov	al,5			;Put color in al, this can be from 0-255
mov	es:[di],al		;Write to seg:ofs
Not to hard to understand is it? Here comes the code to calculate the offset:
mov	ax,320			;You must have declared offs,x and y as word variables (dw)
mul	y
add	ax,x
mov	offs,ax

Nice isnt it? But wouldnt it be even nicer if we could optimize the code? Try to figure out yourself what we can change, remove etc in our code in order to get the most out of it, and then continue the reading.

First of all, we can change "mov es:[di],al" into the more fitting "stosb"...the result is exactly the same. The other thing we can do is to try to remove the "mul" instruction. Why? Because it's slow! A mul instruction can take as much as 42 (the answer to everything - I hope you know your Douglas Adams) clock cykles. Now I'm going to teach you something really usefull! How to optimize your code using SHL and SHR!

Have you ever thought about how nice the instruction SHL (shift left) can be? We can use it in our multiplications instead of using MUL, but it's rather limited. It can only handle an even 2-potency (ie 2^0, 2^1, 2^2, 2^3 etc...). So let's say we want to calculate 5*256. This can be done like this:


mov	ax,5
Shl	ax,8			;2^8 = 256.

Now is'nt that cool? And the best part is that SHL only takes one clock cykle! You can use SHR in the same way, if you want to divide something with an even 2-potency.

"But SHL cant solve our problem! 320 isnt an even 2-potency! you'll shout now. Well, you're half right. 320 isnt an even 2-potency, but we can still use SHL to help us out. Ever thought of what 256+64 is? That's right - 320! So, here is the optimized code for our offset calculation:



mov	di,y
mov	bx,di
shl	bx,8			;We can change this line into "xchg bh,bl". This is a good
shl	di,6			;way to multiply something with 256.
add	di,bx
add	di,x
mov	offs,di

Grrrrreat! Not a single MUL! I'll present now the whole code to display a pixel on screen. Just Cut&Paste the text and compile it with

c:\..\>tasm pixel.asm
c:\..\>tlink /t pixel.obj
.


;---------------------------------------------------------------------------------------
; PIXEL.ASM - Prints a pixel to the screen, TASM version. Written by Cruehead / MiB '98
;---------------------------------------------------------------------------------------

.MODEL SMALL
.CODE
.386
org 100h
START:
jmp StartMeUp

x dw 50					;Play with these values and see how the location of the pixel changes
y dw 40

StartMeUp:

mov 	ax,0013h			;Change mode to 320*200*256
int	10h

mov 	ax,0a000h			;Start of video VGA memory
mov 	es,ax

mov 	di,y				;Calculate offset
mov 	bx,di
xchg 	bh,bl
shl 	di,6
add 	di,bx
add 	di,x

mov	al,10				;Use color number 10 from the standard VGA palette
stosb

waitagain:
in al,60h				;This will wait until the user has pressed the ESC button
cmp al,1
jnz waitagain

mov 	ax,0003h			;We have to switch back to textmode when we're finnished
int	10h

mov	ax,4c00h			;Leave control back to DOS
int	21h

END START

Ok, my work here is done! Hope you understood it. Next time we'll take what we have learned here to make a flashy effect.

As usuall, if you want to ask me something, my email is cruehead_@hotmail.com.

Cruehead / MiB'98


Back to Future project page!Back to Future project page.

Copyright © MiB 1998. All rights reversed.