Code: Select all
;*********************************************
; Boot1.asm
; - A Simple Bootloader
;
; Operating Systems Development Tutorial
;*********************************************
bits 16 ; We are still in 16 bit Real Mode
org 0x7c00 ; We are loaded by BIOS at 0x7C00
start: jmp loader ; jump over OEM block
;*************************************************;
; OEM Parameter block
;*************************************************;
; Error Fix 2 - Removing the ugly TIMES directive -------------------------------------
;; TIMES 0Bh-$+start DB 0 ; The OEM Parameter Block is exactally 3 bytes
; from where we are loaded at. This fills in those
; 3 bytes, along with 8 more. Why?
bpbOEM db "My OS " ; This member must be exactally 8 bytes. It is just
; the name of your OS :) Everything else remains the same.
bpbBytesPerSector: DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs: DB 2
bpbRootEntries: DW 224
bpbTotalSectors: DW 2880
bpbMedia: DB 0xF0
bpbSectorsPerFAT: DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors: DD 0
bpbTotalSectorsBig: DD 0
bsDriveNumber: DB 0
bsUnused: DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber: DD 0xa0a1a2a3
bsVolumeLabel: DB "MOS FLOPPY "
bsFileSystem: DB "FAT12 "
msg db "Welcome to My Operating System!", 0 ; the string to print
;***************************************
; Prints a string
; DS=>SI: 0 terminated string
;***************************************
Print:
lodsb ; load next byte from string from SI to AL
or al, al ; Does AL=0?
jz PrintDone ; Yep, null terminator found-bail out
mov ah, 0eh ; Nope-Print the character
int 10h
jmp Print ; Repeat until null terminator found
PrintDone:
ret ; we are done, so return
;*************************************************;
; Bootloader Entry Point
;*************************************************;
loader:
xor ax, ax ; Setup segments to insure they are 0. Remember that
mov ds, ax ; we have ORG 0x7c00. This means all addresses are based
mov es, ax ; from 0x7c00:0. Because the data segments are within the same
; code segment, null em.
mov si, msg ; our message to print
call Print ; call our print function
xor ax, ax ; clear ax
int 0x12 ; get the amount of KB from the BIOS
cli ; Clear all Interrupts
hlt ; halt the system
times 510 - ($-$$) db 0 ; We have to be 512 bytes. Clear the rest of the bytes with 0
dw 0xAA55 ; Boot Signiture
Code: Select all
loader:
xor ax, ax ; Setup segments to insure they are 0. Remember that
mov ds, ax ; we have ORG 0x7c00. This means all addresses are based
mov es, ax ; from 0x7c00:0. Because the data segments are within the same
; code segment, null em.
When I run this bootloader with qemu even with commenting down the first 3 lines in the loader: label, everything work just fine, but in a real machine it does not, i don't see the output "Welcome to My Operating System!". I tried running the bootloader in a real machine without commenting the two mov instructions that set the ds and es to zero and the program was working as expected.
Probably I haven't understnad correctly how segments work. I mean how does the processor using the ds and es register in order to identify the data?
What if i set ds and es to be equal to 0x7c00 ? I have to try this :p
I understand that my data and instructions are in the code segment, the point is why ds and es must be zero, it does not make sense. It would make more sense if i was initializing them to be 0x7c00 as the code segment.
Why the author of the code does not use segment .text in the assembly code? Is it because when you put everything in the code segment it is self-explanatory so you don't have to explicitly type it?
Does the org actually initialize the cs register to be cs=0x7c00? And how does it know that I'm talking about the code segment (based on my previous question)?
Thank you