VGA Mode 13h in Assembly with Direct Memory Writes

Pushing pixels. Bit blitting. It’s way faster and way funner than using BIOS interrupt routines. If there is a finer way to spend a Sunday afternoon, I do not wish to hear about it.

1. Follow the steps in the previous tutorial, but replace the original text of GraphicsTest.asm with the listing shown below. The new code writes pixels to the display memory area directly, rather than using a BIOS interrupt. It also uses a data structure to represent mode 13h, with information on its identifying number, its display size, and the starting address of its memory area.

use16       ; 16-bit mode

org 0x7C00 ; address of the boot sector

    mov ah,0x00 ; reset disk
    mov dl,0    ; drive number
    int 0x13    ; call BIOS interrupt routine
    ; load sectors from disk using BIOS interrupt 0x13
    mov ah,0x02 ; read sectors into memory
    mov al,0x10 ; number of sectors to read (more than we need)
    mov dl,0    ; drive number
    mov ch,0    ; cylinder number
    mov dh,0    ; head number
    mov cl,2    ; starting sector number
    mov bx,Main ; memory location to load to 
    int 0x13    ; call BIOS interrupt routine
    jmp Main    ; now that it's been loaded

    ; pad out all but the last two bytes of the sector with zeroes
    times ((0x200 - 2) - ($ - $$)) db 0x00

    dw 0xAA55 ; these must be the last two bytes in the boot sector


	; set mode to VGA 13h and draw the default palette
	push DisplayModeInstance13h
	call DisplayModeSet
	mov ax,0 		; pixel x
	mov bx,0 		; pixel y
	mov cx,[NumberOfColors]
		push ax			; pixel x
		push bx			; pixel y
		mov dx,[NumberOfColors]
		sub dx,cx
		push dx			; pixel color index
		call DisplayPixelDrawXY	
		inc ax
		cmp ax,[ColorsPerRow]
		jb EndIfNewRowNeeded
			mov ax,0
			inc bx
	loop DrawEveryColorInPalette
	NumberOfColors: dw 0x0100
	ColorsPerRow: dw 0x0010


	; +0 = number
	; +2 = screen size in pixels
	; +4 = number of colors
	; +6 = address of pixel 0

	dw 0x0000

	dw 0x0013, DisplayModeInstance13hSize, 0x0100, 0xA000
	DisplayModeInstance13hSize: dw 0x0140, 0x00C8 ; 320x200

	; (displayModeToSet)
	push bp
	mov bp,sp
	push ax
	push si
	mov si,[bp+4] ; displayModeToSet
	mov ax,[si+0] ; displayModeToSet.number
	int 0x10
	mov [DisplayModeCurrent],si
	pop si
	pop ax
	pop bp
	ret 2

	; (posX, posY, color)
	push bp
	mov bp,sp
	push ax
	push cx
	push dx
	push si
	push di
	push es
	mov si,[DisplayModeCurrent]
	mov es,[si+6]	; address of display memory
	mov di,[si+2]	; bx = displayModeCurrent.screenSize
	mov cx,[di+0]	; cx = screenSize.x
	mov ax,[bp+6]	; ax = posY
	mul cx		; ax *= cx
	add ax,[bp+8]	; ax += posX
	mov di,ax	; di = offset of pixel	
	mov dx,[bp+4]	; dl = color of pixel
	mov [es:di],dl	; write pixel to memory
	pop es
	pop di
	pop si
	pop dx
	pop cx
	pop ax
	pop bp
	ret 6

    times (0x2000 - ($ - $$)) db 0x00
This entry was posted in Uncategorized and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s