5
\$\begingroup\$

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


   /* linker.ld */ 
   SECTIONS
   {
       /* Set location counter to 0x7c00 */
       . = 0x7c00;
       .text : { *(.text) }
       .data : { *(.data) }
       .other :
       {
            FILL(0x000000)
            . = 0x1ED;
            BYTE(0x55)
            BYTE(0xAA)
       }
   }
\$\endgroup\$
2
\$\begingroup\$
  • 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).

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.