bootloader printing on video memory 0xb8000

2019-07-19 14:37发布

问题:

I am 3-4 days old in assembly programming. trying to print a string in video memory and running through qemu. I expected this program to print Hallo world. But it prints nothing. qemu window prints "Booting From Hard Disk ..." Nothing else

Is it only 16 bit that is allowed in bootloader ? in that case how will I do MMIO ? I was following actual page 32 [ENTERING 32-BIT PROTECTED MODE] of http://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf

[bits 32]
[org 0x7c00]

loop:
    mov edx, 0xb8000
    mov ah,  0x0f

    mov ebx, message
    mov ecx, 0x0
    call draw_string

    ;jmp self_loop
    ;jmp loop

self_loop:
    jmp self_loop

; take the stream begining from ebx
draw_string:
    mov al, [ebx]
    mov ah,  0x0f

    mov [edx], ax
    add ebx, 1
    add edx, 2

    cmp al, 0

    jne draw_string
    ret

message:
    db 'Hallo World', 0x0

times 510 -( $ - $$ ) db 0  ; When compiled , our program must fit into 512 bytes ,
                ; with the last two bytes being the magic number ,
                ; so here, tell our assembly compiler to pad out our
                ; program with enough zero bytes (db 0) to bring us to the
                ; 510th byte.
dw 0xAA55           ; Last two bytes (one word) form the magic number ,
                ; so BIOS knows we are a boot sector.

回答1:

Example for the 16 bit realmode segmented addressing at CPU startup, where the default segment size is limited to 64 KB. In the real mode we can use 32 bit offset register(80386+), but an offset-address have to be pointed inside of the 64 KB size of the segment limit and can not be pointed to an address outside of the 64 KB segment size. (Because we do not need 32 bit offset register for to access an offset between 0 to FFFF, i use 16 bit offset register for this example.) For to access more than only 64 KB we can use an other segment register and/or we can store an other segment address into a segment register.

...

Because the bytes of the hello world message are placed into the code segment, we want to use the same segment address for the data segment register, for to get each byte of the message.

mov ax,cs
mov ds,ax

Now we store the segment address of the textmode video buffer in the extra segment register.

mov ax,0xb800  ; = this is a segment address and not a linear offset address
mov es,ax

lea bx,message ; Now we get the source address in BX
mov di,0x0     ; and the target address for output (upper left corner) in DI

call draw_string

self_loop:
jmp self_loop

; take the stream begining from DS:bx
draw_string:
mov al,[bx]    ; load a byte from the address of DS:BX
mov ah,0x0f

mov es:[di],ax ; store a word to the address of ES:DI
add bx,1
add di,2       ; increasing the target offset address

cmp al,0
jne draw_string
ret