问题
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
来源:https://stackoverflow.com/questions/22961979/bootloader-printing-on-video-memory-0xb8000