# The beginnings of a bootloader using GNU-based tools

This is a personal project of mine. I am currently in the research phase of developing my own bootloader that will be used to load a single task operating system. I am far away from the final goal, but have been trying to document my process as a reference. The content of my code documentation and code can be found at Bootloader 101.

If possible I would appreciate feedback. The wiki page is open to be edited, and if you feel like you can contribute please feel free to do so. I apologize beforehand for referencing you to another page. The format of the content is important.

First piece of code:

   # Author: Matthew Hoggan
# Date Created: Tuesday, Mar 6, 2012
.code16                        # Tell assembler to work in 16 bit mode (directive)
.section .text
.globl _start                  # Help linker find start of program
_start:
movb $0x0e, %ah # Function to print a character to the screen movb$0x00,     %bh        # Indicate the page number
movb $0x07, %bl # Text attribute mov$'A',      %al        # Move data into low nibble
int  $0x10 # Video Service Request to Bios _hang: jmp _hang .end /* linker.ld */ SECTIONS { /* Set location counter to 0x7c00 */ . = 0x7c00; .text : { *(.text) } .data : { *(.data) } .other : { FILL(0x000000) . = 0x1F2; BYTE(0x55) BYTE(0xAA) } }  Second piece of code:  # Author: Susam Pal <http://susam.in/> .code16 # Tell the assembler to use 16 bit instructions .section .text .globl _start _start: # Tell linker where entry point into program is mov$0xb800, %ax           # 0xb800 is the start address of character buffer
mov %ax, %ds               # Move that address into the data segment
movb $'B', %ds:0x00 # Write data directly to that buffer at 0 movb$0x1e, %ds:0x01       # Write text attributes for the text right after
idle:
jmp idle

SECTIONS
{
/* Set location counter to 0x7c00 */
. = 0x7c00;
.text : { *(.text) }
.data : { *(.data) }
.other :
{
FILL(0x000000)
. = 0x1ED;
BYTE(0x55)
BYTE(0xAA)
}
}


• Your code is well-commented. Other answers on this site mention the importance of good comments: and yours are good.
• An infinite loop at the end of the program is strange; instead I would have expected a ret or retf statement to return to the O/S shell which launched this program; but maybe that's different/excusable for what may in future evolve to become a boot-loader.
• Writing to memory at 0xb8000 may or may not work depending on the current video mode. Here is a thread which discusses whether it's safe to assume 0xb8000 on computer startup (perhaps it is, but there are alternatives)
• You code would be more compact (perhaps less readable) if you initialized entire words, instead of separate instructions for each byte; for example in the first program you could initialize ax and bx; and in the second program you could write 0x1E42 into the first word of video memory.
• Using the 2nd method you'll probably start writing whole strings (not single characters) to the screen; the lods/stos/movs opcodes are useful for that. For example, you could do:

mov $0x1e, %ah # Write text attributes for the text right after loop: lodsb # load byte from ds:si and increment si cmp$0x00, %al # test for end-of-string
jz done
stosw          # store word (not byte) to es:di and increment di
jmp loop       # loop back to load-and-then-store next byte of the string
done:

• For this kind of reason it's unconventional of you to use the ds register to point to video memory; I would have expected you to use the es register instead.

• According to the GNU Assembler manual if you write %ds:0x00 then it will emit the ds prefix, which is unnecessary (I think that ds is the default segment for memory access); perhaps (based on the manual, I don't know) the syntax without the segment prefix is something like just 0x00 or perhaps 0x00(,1).

(I'm unable to give you feedback on the linker.ld section).

• The 'test for zero' cmp \$0x00, %al could be written more compactly using something like or %al, %al – ChrisW Feb 25 '14 at 22:23