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 0ドルx0e, %ah # Function to print a character to the screen
movb 0ドルx00, %bh # Indicate the page number
movb 0ドルx07, %bl # Text attribute
mov $'A', %al # Move data into low nibble
int 0ドルx10 # 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 0ドルxb800, %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 0ドルx1e, %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)
}
}
1 Answer 1
- Your code is well-commented. Other assembly 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
orretf
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
andbx
; 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 0ドルx1e, %ah # Write text attributes for the text right after loop: lodsb # load byte from ds:si and increment si cmp 0ドルx00, %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 thees
register instead.- According to the GNU Assembler manual if you write
%ds:0x00
then it will emit theds
prefix, which is unnecessary (I think thatds
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 just0x00
or perhaps0x00(,1)
.
(I'm unable to give you feedback on the linker.ld
section).
-
\$\begingroup\$ The 'test for zero'
cmp 0ドルx00, %al
could be written more compactly using something likeor %al, %al
\$\endgroup\$ChrisW– ChrisW2014年02月25日 22:23:25 +00:00Commented Feb 25, 2014 at 22:23