Invalid Hello World bootloader

I am working on tutorials on this web page , which gradually creates a bootloader that displays Hello World.

The second tutorial (where we try to get an “A” for output) works fine, and yet the 1st tutorial doesn't work for me at all! (The BIOS completely ignores the floppy disk and boots directly into Windows). This is not a problem, although any explanation will be appreciated.

The real problem is that I cannot get the 3rd tutorial to work. Instead, when I output "Hello World", I get an unusual character (and a blinking cursor) in the lower left corner of the screen. It looks a bit like a smiley in a round rectangle. Does anyone know how to make Hello World display properly?

+5
source share
2 answers

You say “boot straight into windows”, so I assume that you are using a physical PC. In the future, pay attention: always use the emulator for development! It is just easier. I like Bochs for OSDeving because it has good debugging features. Now, for a possible solution.

There are many BIOS errors that violate the unofficial IBM PC specifications for the 0x7C00 boot address.

This can lead to a lot of problems with memory addresses and with every collection. So make a start like this:

[BITS 16] ;tell the assembler that its a 16 bit code
[ORG 0x7C00] ;this tells the assembler where the code will be loaded at when it runs on your machine. It uses this to compute the absolute addresses of labels and such.

jmp word 0:flush ;#FAR jump so that you set CS to 0. (the first argument is what segment to jump to. The argument(after the `:`) is what offset to jump to)
;# Without the far jmp, CS could be `0x7C0` or something similar, which will means that where the assembler thinks the code is loaded and where your computer loaded the code is different. Which in turn messes up the absolute addresses of labels.
flush: ;#We go to here, but we do it ABSOLUTE. So with this, we can reset the segment and offset of where our code is loaded.
mov BP,0 ;#use BP as a temp register
mov DS,BP ;#can not assign segment registers a literal number. You have to assign to a register first.
mov ES,BP ;#do the same here too
;#without setting DS and ES, they could have been loaded with the old 0x7C0, which would mess up absolute address calculations for data. 

, - 0x07C0:0000 ( ) 0x0000:7C00. , . "" , ( , , . )

jmp word 0:0x7C04 ;# 0x7C04 is the address of the `flush` label 
...

, .

. , ?

, :

mov ax,[mydata]
hlt

mydata: dw 500 ;#just some data

-

mov ax,[0x7C06] 

, , , ? , , DS 0x7C0? 0:0x7C06 0x7C0:0x7C06, .

, . , , .

+7

, , , .

[ORG 0x7C00]    ;Origin, tell the assembler that where the code will

, , , . , DS- . - , push pop of ds , , ,

 push cs
 pop ds

.

 [ORG 0x000]    ; switched to 0 since we are going to try to correct it ourself

 call nextinstruction
 nextinstruction:    ; get the return address of the call into dx
 pop dx              ; which is essentially the start of the code + 3 (3 bytes for the call instruction)
 MOV SI, HelloString ;Store string pointer to SI
 add si, dx          ; add IP from start of program
 sub si, 3           ; subtract the 3 the call instruction probably took
 push cs
 pop ds              ; make ds the same as cs.  
 CALL PrintString   ;Call print string procedure
 JMP $      ;Infinite loop, hang it here.

, DS . , , SI, DS .

DS - , - Art of Assembly, .

Earlz , , , . , .

+1

All Articles