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

BootStageOne:
    ;
    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
    ;

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

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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Main:
	; 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]
	DrawEveryColorInPalette:
		;
		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
		EndIfNewRowNeeded:
	loop DrawEveryColorInPalette
	;
	ret
	;
	NumberOfColors: dw 0x0100
	ColorsPerRow: dw 0x0010

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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

DisplayModeCurrent:
	dw 0x0000

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

DisplayModeSet:
	; (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

DisplayPixelDrawXY:
	; (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

PadOutSectorsAllWithZeroes:
    times (0x2000 - ($ - $$)) db 0x00
Advertisements
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:

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s