; This bootsector makes some basic initialization and prints the ; canonical hello world in real mode. ;real-mode segments %define LOADSEG 0x07C0 %define STACKSEG 0x9000 ; This seems to be the typical place for a stack %define VIDEOSEG 0xB800 ;BIOS functions %define BIOS_10_PUTCHAR 0x0E %define BIOS_16_GETKEY 0x00 ;text styles %define PLAIN 0x07 %define EMPH 0x20 [BITS 16] ; the BIOS starts out in 16-bit real mode [ORG 0] ; data offset = 0 jmp start ; skip over our data and functions, we cannot execute data :-), ; well, you can, but i am not held responsible for the results :) ;******************************************* ; Data used in the boot-loading process ;******************************************* ;data bootdrv db 0 ;messages bootmsg db 'ONABSE-MIN, from Pietro Braione',13,10 db 'V.1.0 jan 2003',13,10,0 rebootmsg db 'Press any key to reboot',13,10,0 helloworld db 'Hello, world!',13,10,0 ; A very informative message ;******************************************* ; Procedures we are going to use ;******************************************* message: ; Dump ds:si to screen. ; Modifies: ax, bx, si + int 0x10 func 0x0E side effects. lodsb ; Load byte at ds:si into al or al,al ; Test if character is 0 (end) jz .done mov ah,BIOS_10_PUTCHAR ; Put character mov bx,PLAIN ; Attribute int 0x10 ; Call BIOS jmp message .done: ret ; ******************************************************************** getkey: ; Waits for a keypress. ; Modifies: ah + int 0x16 func 0 side effects. mov ah,BIOS_16_GETKEY int 0x16 ret ; ******************************************* ; The actual code of our boot loading process ; ******************************************* start: ; Adjust segment registers mov ax,LOADSEG ; BIOS loads bootsector at segment LOADSEG. We set ds accordingly mov ds,ax ; so we don't have to add LOADSEG<<4 to all our data addresses ; Quickly save what drive we booted from mov [bootdrv], dl ; Set up a stack mov ax,STACKSEG cli ; Disables interrupts mov ss,ax mov sp,0xFFFF ; Let's use the whole segment. Why not? We can :) sti ; Puts interrupts back on ; When setting up a stack, interrupts MUST be disabled and NO procedure ; can be called, since interrupts and calls need a stack to work. ; The Intel 386 Programmer Reference Manual specifies: ; "A MOV into SS inhibits all interrupts until after the execution of the ; next instruction (which is presumably a MOV into eSP)." ; This means that we can remove the cli and sti above and save 2 bytes. ; I left them commented for didactic purposes :) ; Note that in general when interrupts are disabled things must be ; done as quickly as possible to minimize the number of lost interruptions ; from clock, peripherals, etc. Here we are at boot time so we ; don't have this issue. ; Now for the real stuff! mov si,helloworld call message ; we're done - short, ain't it? jmp $ ; hangs ; ******************************************* ; Epilogue ; ******************************************* ; pads with zero to sector size - 2 times 510-($-$$) db 0 dw 0xAA55 ; marks as boot sector ; pads with zeros to floppy size - use it if necessary ; (it isn't with Bochs and VMware) ;times 1474560-($-$$) db 0