Basic boot loader using GAS

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Adel
Posts: 3
Joined: Sun Sep 29, 2013 2:39 pm
Location: International Date Line

Basic boot loader using GAS

Post by Adel »

Hey,

I am working to get a very basic(hello-world thing) boot-loader running; I read some examples online, followed their steps and got it working.
Using

Code: Select all

nasm -f bin
, then copy it to a floppy and use qemu to load it.

What I am trying to do now is simply re-do that but using GAS (my brain's convinced me I am more familiar with AT&T syntax, somehow).

So here's my code, I added some comments as I was trying to understand each step.
Please let me know if these indicate any problem with my understanding of what's going on:

Code: Select all

	.code16			# 16-bit assembly 
	.org 0x7C00		# We MUST be loaded here 


	#	L0 is loop-begining and L1 is loop exit
	#	BIOS INT 10H: (Video)
	#	AH: 0EH (the type of the printing - here Teletype)
	#	AL: The character I will print
	#	BH: 00H (The video page number)
	#	BL: 02H (Color of the text - 0/black back , 2/green front)
	
	movw $my_hello, %si	#Put the &my_hello[0] in the %si
	call print_string
	jmp .			#Jump to self - loop forever
	
print_string:
L0:
	movb (%si), %al		#Move the character to AL for printing
	cmpb $0, %al		#Did we reach the \0 terminator?
	je   L1			#Yes? Jump to end
	call print_char		#No?  Print the character
	inc  %si		#Increment to the next character
	jmp  L0			#Repeat
L1:
	ret

print_char:
	#CAREFUL: I am assuming the char is in the AL already
	movb $0x0E, %ah		#Teletype
	movb $0x00, %bh		#Page No: 0
	movb $0x02, %bl		#black|green
	int  $0x10		#Calling the bios
	ret
	
	#My Data
	my_hello:
		.asciz "Hello, world!"
	.org .+510, 0		#Move the location counter to current+510
				#and pad in between with 0s
	.word 0xAA55		#end with the bootloader marker
Next, I assembled it with as; that produces an ELF so I used

Code: Select all

objcopy -O
binary and then copied it using

Code: Select all

dd
and loaded it with

Code: Select all

qemu-system-i386
; it complained that the floppy is not bootable.

In what step have I erred here? Any tips where I should be looking for the error?
I used hexdump to compare the binary outputs of both my NASM and GAS attempts, they seem to differ but I am not sure why; is it something related to the

Code: Select all

.org
instruction?

Another question:
The same assembly in nasm syntax worked; how did it work properly when I didn't set the stack segment, considering that I have used the call and the ret instructions? Am I missing something here?

Thanks,
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Basic boot loader using GAS

Post by iansjack »

You are moving the program counter too far when writing the boot signature. .+510 moves it 510 bytes from the current location; you want 510 bytes from the start of the program.
Adel
Posts: 3
Joined: Sun Sep 29, 2013 2:39 pm
Location: International Date Line

Re: Basic boot loader using GAS

Post by Adel »

Ouch :oops:
Thanks for pointing that out.

The problem persists, though; I noticed that when copying the binary file using dd I somehow copy 32KBs.
(When I was following the many examples online using NASM, dd reported copying exactly 512 bytes)

Do you suggest any place of where I should be looking?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Basic boot loader using GAS

Post by Combuster »

Start by looking where everything you wanted actually ended up in those 32kb. I'm guessing you start off with either platform-specific garbage or 0x7C00 bytes worth of zeroes. Then you can check each of the intermediated to see where it came from.

You'll probably be going to end up with a linker script to get the actual placement for a flat binary right.

Or... *drumroll* NASM :wink:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Adel
Posts: 3
Joined: Sun Sep 29, 2013 2:39 pm
Location: International Date Line

Re: Basic boot loader using GAS

Post by Adel »

Just so others can avoid such a mistake, let me explain what was going on and what's the fix:

The problem:
The ".org" directive at the beginning actually says: Move the location counter from 0x0 to 0x7C00 and padd the in-between area with 0s.
Hence why dd was reporting a large block being copied.

The fix:
What I did is that I removed the .org directive; how would I then make sure that the binary will be loaded at the correct place in memory?
"ld --Ttext 0x7C00" does it, it says that the text section starts there; and while we are at it, there's no point in using objcopy, just add the flag "--oformat binary" to the ld to convert the ELF file "as" gave us into a flat binary file and it's all done.


The next thing that I am still missing is:
How is the routine calling working when I am not setting the stack segment? As far as I read, nothing guarantee that it has some default value all the time, maybe I missed something?
Last edited by Adel on Tue Oct 01, 2013 4:20 pm, edited 1 time in total.
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Basic boot loader using GAS

Post by iansjack »

The BIOS initialization will have set SS and SP to some values (offhand, without looking, I've no idea what these values are or whether they are the same for different BIOS implementations). It just so happens that in your case these values correspond to valid memory locations that you are not otherwise using. So you have a stack that is enough to make at least one level of subroutine/interrupt call - it's just that you don't know where that stack is or how much stack you can safely use (if any).

Clearly this is very bad practice and is liable to lead to tears before bedtime. Do the decent thing and set up a stack that is under your control before you start using it.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Basic boot loader using GAS

Post by Combuster »

Basic sanity says that the bios does leave a "working" stack for its own use because the timer interrupt would have to run, and you can assume it's not overlapping 0x7C00-0x7E00 because then timer interrupts would mess up the bootsector - possibly before your code would even get run.

That said, anything but the most trivial bootsectors access something outside this safe range, and might potentially even perform enough nested calls to overflow the stack, so not setting SS/SP is always listed as a bug upon code review for good reason. It just so happens that by means of probability, quite a few unknowing people are lucky enough get away without it :wink:

And to be honest, I've never caught someone actually getting hit by that stack issue, because when both symptoms do happen there's always something else wrong as well. :-k
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply