Bootsector executed, CPU in pmode: How to write a string on the screen?
Login asks:
Hi, I've been written a bootsector that initalys a stack, DS segment, end put the CPU in Protected Mode. But when the CPU is in Pmode, I can't use the int 10h func. 0Eh for writting characters on the screen. How can I do ???? PLEASE? HEEELLLLLPPPP
My answer:
The easiest way to write characters or strings on the screen directly after switching into PMode is to assign the value 0xB800 to FS while in real-mode. When you switch into PMode, FS is not a valid GDT selector but you can use it as well!
At boot time, the console is 80x25 16-bit wide characters. That means the offset of the 16-bit character will be (x+160*y). I use 32-bit integer to store 2-byte strings for debuging purpose during boot.
Example in NASM syntax:
; fs=0xb800 (before switching into pm)
mov eax, dword [debug_ok]
mov [fs:160], eax
; ...
debug_ok:
db 'O',0x0a,'K',0x0a ; 'OK' in green on black
The attribute byte format is:
bits 7 6 5 4 3 2 1 0 +----+----+----+----+----+----+----+----+ | BL | BACKGROUND | FOREGROUND | +----+--------------+-------------------+ BL=1 makes the character blinking. Values for BACKGROUND and FOREGROUND: 0x0 BLACK (default for BACKGROUND in BIOS) 0x1 BLUE 0x2 GREEN 0x3 CYAN 0x4 RED 0x5 MAGENTA 0x6 BROWN 0x7 LIGHTGRAY (default for FOREGROUND in BIOS) ; as BACKGROUND is 3-bit, the following colours are not available ; for background 0x8 DARKGRAY 0x9 LIGHTBLUE 0xa LIGHTGREEN (I love that... It remembers me the Amstrad ;) 0xb LIGHTCYAN 0xc LIGHTRED 0xd LIGHTMAGENTA 0xe YELLOW 0xf WHITE ; (from conio.h (djgpp))
Here is a cputs() style function (pmode). It takes an ASCIIZ string in ESI and puts it at (X+Y*80) position stored in ECX. It does not need FS to equal 0xb800 but it would have been shorter.
write:
lodsb ; per character write
mov ah, 0x0a ; LIGHTGREEN on BLACK, no BLinking
and al,al
jz .wri_1
call .wri_2
inc ecx
jmp write
.wri_2
push ecx
push edi
mov edi, 0xB8000
shl ecx, 1 ; 16-bit characters
mov word [edi+ecx], ax
pop edi
pop ecx
.wri_1
ret
Example call:
mov ecx, 8*80 ; print it at (0,8)
mov esi, msg
call write
;
msg: db 'message', 0x00
Hope this helped...
Leave a Comment