Snippets

Sylvester Rac Read planar from VGA in text mode 3

Updated by Sylvester Rac

File Test2v3.asm Modified

  • Ignore whitespace
  • Hide word diff
 ; Set Graphics controller Miscellaneous Graphics Register (Index 06h) = 0x0C (turn off bit 1 Chain Odd/Even Enable)
 ; Read from memory and try to find the known data
 
+; To build:
+; nasm Test2v3.asm -o Test2v3.com
+
 SECTION .data
 
 ; Info on vga modes:
Created by Sylvester Rac

File Test2v3.asm Added

  • Ignore whitespace
  • Hide word diff
+
+; Test2v3.asm
+; Leave in default mode 3
+; Graphics controller Miscellaneous Graphics Register (Index 06h) = 0x0E
+; Output known data @B8000
+; Set Graphics controller Miscellaneous Graphics Register (Index 06h) = 0x0C (turn off bit 1 Chain Odd/Even Enable)
+; Read from memory and try to find the known data
+
+SECTION .data
+
+; Info on vga modes:
+; http://www.columbia.edu/~em36/wpdos/videomodes.txt
+; http://www.brokenthorn.com/Resources/OSDevVid2.html
+
+intromessage:	db 'Test Graphics controller (Index 06h) Chain Odd/Even Enable bit', 13, 10
+				db 'Press any key to continue'
+				db 13,10,'$'
+knowndata:		db 'a',0x17,'b',0x17,'c',0x17,'d',0x17,'e',0x19,'f',0x19,'g',0x19,'h',0x19,'i',0x1c,'j',0x1c,'k',0x1c,'l',0x1c,'m',0x1e,'n',0x1e
+				db 'o',0x1e,'p',0x1e,'q',0x1a,'r',0x1a,'s',0x1a,'t',0x1a,'u',0x18,'v',0x18,'w',0x18,'x',0x18,'y',0x10,'z',0x10,'!',0x10,' ',0x10
+knowndataLen:	equ $ - knowndata			; determine data length
+msgBuffer1Equal:	db 'Success, buffer1 matched the known data'
+					db 13,10,'$'
+msgBuffer1Unequal:	db 'Error, buffer1 did not match the known data'
+					db 13,10,'$'
+msgBuffer2Equal:	db 'Success, buffer2 matched the known data'
+					db 13,10,'$'
+msgBuffer2Unequal:	db 'Error, buffer2 did not match the known data'
+					db 13,10,'$'
+initialMode:	db 0x00
+msgInitialMode:	db 'Initial video mode: 0x'	    ; string to output
+valInitialMode:	dw 0x0000						; placeholder for 2 byte hex value
+				db 13,10,'$'					; newline
+
+
+SECTION .bss
+
+buffer1:	resb 56		; reserve 28 * 2 bytes
+buffer2:	resb 0x8000		; reserve 32Kb
+
+
+SECTION .text
+org 0x100
+GLOBAL _start
+
+_start:
+
+; print intro message
+mov ah,0x09
+mov dx,intromessage
+int 0x21
+
+
+; save initial video mode
+mov ax,0x0f00	; ah=0f: VIDEO - GET CURRENT VIDEO MODE
+int 0x10		; returns: AL = display mode
+mov [initialMode],al
+
+; print "Initial video mode:"
+push ax
+call ConvertByteToHex		; convert al into hex value @ DS:[BX]
+add sp,2
+mov [valInitialMode],ax
+mov ah,0x09
+mov dx,msgInitialMode
+int 0x21
+
+
+;
+; Wait for a keypress
+;
+mov ah, 0x00
+int 0x16
+
+; 80 x 25 row text mode
+; each row is 160 bytes (even byte = character, odd byte = attribute)
+mov ax, 0xb800
+mov es, ax
+mov di, 0				; destination: ES:DI
+mov si, knowndata		; source: DS:SI
+mov cx, knowndataLen
+rep movsb
+
+; read memory into buffer1 (56 bytes)
+push ds		; save data segment!!
+mov ax, ds
+mov es, ax
+mov di, buffer1			; destination: ES:DI
+mov ax, 0xb800
+mov ds, ax
+mov si, 0				; source: DS:SI
+mov cx, 56
+rep movsb
+
+pop ds		; restore our data segment
+
+
+;
+; Disable Chain Odd/Even
+; Clear bit 1 of Graphics controller Miscellaneous Graphics Register (Index 06h)
+;
+mov dx, 0x3ce
+mov al, 0x06
+out dx, al
+inc dx
+in al, dx
+and al, 0xfd		; clear bit 1
+out dx, al
+
+
+;
+		mov dx, 0x3ce
+		;mov ax, 0x0005	; set index 5 (Shift256/Shift Reg/Host O/E/Read Mode/Write Mode) to 0
+		mov al, 0x05
+		out dx, al
+		inc dx
+		mov al, 0x00
+		out dx, al
+;
+		;set bitplane 2
+		mov dx, 03c4h
+		;mov			ax, 0402h
+		mov al, 0x02
+		out dx, al
+		inc dx
+		;;mov al, 0x0f		; this selects the planes to read from when Seqencer bit 3 index 4 is clear
+		;;mov al, 0x03		; this selects the planes to read from when Seqencer bit 3 index 4 is clear
+		mov al, 0x01
+		out dx, al
+;
+
+
+;
+; Sequencer: Disable Chain 4/Disable Odd/Even Host Memory Write Adressing
+; Clear bit 3, Set bits 2 and 1 of Sequencer Memory Mode Register (Index 04h)
+;
+mov dx, 0x3c4
+mov al, 0x04
+out dx, al
+inc dx
+mov al, 0x06
+out dx, al
+
+		mov dx, 0x3ce
+		mov al, 0x04	; Graphics controller index 4 (Read Map Select)
+		out dx, al
+		inc dx
+		mov al, 0x00	; 0x00 = read from plane 0!!
+		out dx, al
+;
+
+
+; read memory into buffer2 (56 bytes)
+push ds		; save data segment!!
+mov ax, ds
+mov es, ax
+mov di, buffer2			; destination: ES:DI
+mov ax, 0xb800
+mov ds, ax
+mov si, 0				; source: DS:SI
+mov cx, 0x8000
+rep movsb
+
+pop ds		; restore our data segment
+
+
+;
+; Wait for a keypress
+;
+mov ah, 0x00
+int 0x16
+
+; restore the inital video mode
+mov ah, 0x00	; ah=00: VIDEO - SET VIDEO MODE
+mov al, [initialMode]
+int 0x10
+
+; compare buffer1 with knowndata
+mov si, knowndata		; ds:si points to first string
+mov di, buffer1			; ds:di points to second string
+mov cx, 56
+call _compare_strings
+
+; print result
+cmp ax, 0
+;cmp bx, 56
+jnz buffer1_uneq
+mov dx,msgBuffer1Equal
+jmp print_message1
+buffer1_uneq:
+mov dx,msgBuffer1Unequal
+print_message1:
+mov ah,0x09
+int 0x21
+
+; compare buffer2 with knowndata
+mov si, knowndata		; ds:si points to first string
+mov di, buffer2			; ds:di points to second string
+mov cx, 56
+call _compare_strings
+
+; print result
+cmp ax, 0
+jnz buffer2_uneq
+mov dx,msgBuffer2Equal
+jmp print_message2
+buffer2_uneq:
+mov dx,msgBuffer2Unequal
+print_message2:
+mov ah,0x09
+int 0x21
+
+; dump the buffer
+push ds
+push buffer1
+push 56
+call _hexdump_string
+add sp,6
+
+; dump the buffer
+mov si, buffer2
+xor cx, cx
+dumploop:
+; print address (just cx for now)
+mov al, cl
+push ax
+call ConvertByteToHex		; convert al into hex value @ DS:[BX]
+add sp,2
+mov [valBufferIndex],ax
+mov ah,0x09
+mov dx,msgBufferIndex
+int 0x21
+; output 256 bytes @ ds:si
+push ds
+push si
+push 256
+call _hexdump_string
+add sp,6
+add si, 256
+inc cx
+cmp cx, 128
+jz terminate
+
+;
+; Wait for a keypress
+;
+mov ah, 0x00
+int 0x16
+cmp al, 'x'		; allow user to terminate
+jz terminate	; in case 'x' is pressed
+
+jmp dumploop
+
+; terminate application
+terminate:
+mov ax,0x4c00
+int 0x21
+
+
+msgBufferIndex:	db 'Dumping buffer address 0x'	; string to output
+valBufferIndex:	dw 0x0000						; placeholder for 2 byte hex value
+				db '00 (press "x" to exit)',13,10,'$'				; newline
+
+
+;
+; Compare strings @DS:SI, ES:DI (max string length to compare specified in cx)
+; Return:
+;	AX: 0 if strings are equal, else 1
+;	BX: Number of equal characters found
+;
+_compare_strings:
+	push bp
+	mov bp,sp
+	push dx
+	push si
+	push di
+
+	cld
+	xor bx, bx
+.cmploop:
+	lodsb			; load al with char from string 1
+					; note: lodsb increments si automatically
+	cmp [di], al	;
+	jne not_equal
+	inc di
+	inc bx
+	cmp bx, cx		; did we reach the end of the string?
+	jne .cmploop
+
+	mov ax, 0		; strings were equal
+	jmp end_compare_strings
+
+not_equal:
+	mov ax, 1		; strings were not equal
+
+end_compare_strings:
+	pop di
+	pop si
+	pop dx
+	pop bp
+
+RET
+
+
+;
+; Output string as hexadecimal values
+; We use bios call rather than DOS string functions
+; Parameters:
+;	bp+8: string (segment)
+;	bp+6: string (offset)
+;	bp+4: string (length)
+;
+; Locals:
+;	bp-2:
+;	bp-4: highlight colour
+_hexdump_string:
+	push bp
+	mov bp,sp
+	push ax
+	push bx
+	push cx
+	push dx
+	push si
+	push ds
+
+	mov ax, [bp+8]
+	mov ds, ax
+	mov si, [bp+6]
+	xor cx, cx
+.hexloop:
+	cmp cx, [bp+4]
+	jz end_hexloop
+	lodsb			; load al with char from DS:SI
+	push ax
+	;
+	; determine colour (highlight values from 'a' to 'z')
+	mov byte [bp-4], 0x07
+	cmp al, 'a'
+	jl .pr1			; jump if less than
+	cmp al, 'z'
+	jg .pr1			; jump if greater than
+	mov byte [bp-4], 0x18
+.pr1:
+	;
+	;
+	call ConvertByteToHex		; convert al into hex value
+	add sp,2
+	mov [val_hex],ax
+	mov bl, [bp-4]
+	call _SpPrintChar
+	mov ax, [val_hex]
+	mov al, ah
+	mov bl, [bp-4]
+	call _SpPrintChar
+	mov al, 0x20
+	call _PrintChar
+	mov al, 0x20
+	call _PrintChar
+	inc cx
+	mov dl, cl			; if (cx % 16 == 0)
+	and dl, 0x0f		;
+	jnz .hexloop		;
+	mov al, 0x0d		; print a newline character every 16 bytes
+	call _PrintChar		;
+	mov al, 0x0a		;
+	call _PrintChar		;
+	jmp .hexloop		;
+end_hexloop:
+	mov al, 0x0d
+	call _PrintChar
+	mov al, 0x0a
+	call _PrintChar
+
+end_hexdump_string:
+	pop ds
+	pop si
+	pop dx
+	pop cx
+	pop bx
+	pop ax
+	pop bp
+
+RET
+
+val_hex		dw 0
+
+
+_PrintChar:	                    ;Procedure to print character on screen
+	                            ;Assume that ASCII value is in register AL
+MOV AH, 0x0E	                ;Tell BIOS that we need to print one charater on screen.
+MOV BH, 0x00	                ;Page no.
+MOV BL, 0x07	                ;Text attribute 0x07 is lightgrey font on black background
+INT 0x10	                    ;Call video interrupt
+
+RET		                        ;Return to calling procedure
+
+
+_SpPrintChar:	                    ;Procedure to print character on screen
+push ax
+push bx
+push cx
+	                            ;Assume that ASCII value is in register AL
+MOV AH, 0x09	                ;Tell BIOS that we need to print one charater on screen.
+MOV BH, 0x00	                ;Page no.
+;;MOV BL, 0x07	                ;Text attribute set by caller
+MOV CX, 0x01
+INT 0x10	                    ;Call video interrupt
+
+; advance the cursor because BIOS doesn't do it
+mov ah, 0x03
+mov bh, 0x00
+int 0x10
+inc dl
+mov ah, 0x02
+mov bh, 0x00
+int 0x10
+
+pop cx
+pop bx
+pop ax
+RET		                        ;Return to calling procedure
+
+
+;
+; ConvertByteToHex
+;
+; Convert btye in AL to 2 digit Hexadecimal string
+; Result returned at WORD address referenced by DS:[BX]
+;
+
+ByteToHexTable:
+    db '0123456789ABCDEF', 0
+
+ConvertByteToHex:
+	push bp
+	mov bp,sp
+
+    push bx
+	mov ax,[bp+4]
+    lea   bx, [ByteToHexTable]
+    mov   ah, al            ;make al and ah equal so we can isolate each half of the byte
+    shr   ah, 4             ;ah now has the high nibble
+    and   al, 0x0F          ;al now has the low nibble
+    xlat                    ;lookup al's contents in our table
+    xchg  ah, al            ;flip around the bytes so now we can get the higher nibble 
+    xlat                    ;look up what we just flipped
+    pop bx
+
+	pop bp
+
+RET		                            ;Return to calling procedure
+
HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.