Printing string behaves oddly from loaded disk sector

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
twtty
Posts: 8
Joined: Wed Feb 10, 2016 6:30 pm

Printing string behaves oddly from loaded disk sector

Post by twtty »

Hello, I am new to this forum. I have considered joining for a while now, but have not until now... Thank God for bugs, huh? :wink:

Over the past hours, I have been messing around with floppy drives. It seems as though I have sort of managed to load the file I have been after loading, only it is just certain functionality within the loaded (and then "jmp:d" to) file that seems to be working properly.

What I have is two files (I am attempting to create a multiboot bootloader), a boot.asm (stage 1) and a loader.asm (stage 2). I then compile these to a boot.bin and a loader.bin respectively. I then merge these files into one file (each file at the moment contains 512 bytes for testing purposes - oh and hey, the STAGE 1 file contains 512 bytes for obvious reasons). In the merged file, the contents of boot.bin comes first and the contents from loader.bin comes after. The file they are merged into is called floppy.img (and is called that to represent a floppy). The floppy.img is however not formatted to be in a particular "file system layout" (such as FAT-12, FAT-16, ext, etc.), it is simply the binary from the two files "stacked on top of each other".

Whilst the STAGE 1 (boot.asm) contains the 0xaa55, that logically is what is booted by the BIOS. In that file, I attempt loading the second file (which honestly is not really a file, only a disk sector - but you know this 8) ); I attempt loading the second file into 0x1000:0x0000, which I am pretty sure works. I then do a jump over to that location (0x1000:0x0000) and the code is executed (at least I am pretty sure it is executed, more about that in just a second). The thing is, it acts rather weird...

Image

What you are seeing here is what happens when I run the bootloader in Bochs. The "broad" steps that happens are...
  • 1. "Booting from floppy..." (from Bochs, telling us we are booting from a floppy)
    2. "Boot, stage one." (printed by the STAGE 1 (or boot.asm (whoah, there are a lot of brackets (in here))), it means that STAGE 1 was successfully ran)
    3. "*" (printed by the STAGE 1 - indicates that the floppy sector was successfully loaded)
    4. "The things from after the '*' but before the 'u'" (assumably printed by STAGE 2, this is supposed to say "Boot, stage two." - it evidently does not)
    5. "u" (printed by STAGE 2, right after printing the string which evidently does not display correctly - for some reason the "u" turns out fine. It is however printed using a slightly different method which you will see in the code below.
I am not a hundred percent sure that I am completely right about these five steps. There is after all a bug somewhere that is messing something up. Hopefully by seeing the (quite short, it is mostly comments) code for these two files, somebody will be able to point out what I am doing wrong. Apologies for not being able to strip the code down into smaller pieces. I really do not know what is wrong! :(

Something to note: there is a similar print function in the STAGE 1, which opposed to the print function in STAGE 2 is working. I have tried changing its name and... Well, many many many more things... I was highly surprised when I noticed that it was possible to print out a "u" (or any other ASCII symbol) to the "VGA monitor" for that matter.

Once again, many apologies for the rather big chunk of code.

Here is the STAGE 1 (boot.asm):

Code: Select all

; Since we enter in 16 bit realmode
[bits 16]

; Set the offset, this is where the BIOS loads us
[org 0x0]

; Far jump to start
jmp start

; DEFINE INNER FUNCTIONS
; PRINT STRING
; Function for printing strings
Print:
	mov ah, 0eh		; Used for printing a character to the screen
PrintString:
	lodsb 			; Take the next character (byte) from SI and store in AL
	and al, al		; Pointless operation to check whether or not AL is zero
	jz PrintDone 	; If it is, the print is finished
	int 10h			; Execute
	jmp PrintString ; Carry on printing until zero has been found 
PrintDone:
	ret 			; Return back to from where function was called

; LOAD BOOT LOADER STAGE TWO
; Load sectors from second boot loader into memory
Stage:
	mov di, 05h				; Five tries to load
StageReset:
	mov ah, 0				; Reset disk function
	mov dl, 0				; Disk type is floppy
	int 13h					; Invoke BIOS
	jc StageReset 			; Upon error, retry
StageReadLoopPrepare:
	mov ah, 02h				; BIOS read sector
	mov al, 1				; Read one sector
	mov ch, 0				; Read from same track
	mov cl, 2				; Sector to read
	mov dh, 0				; Head number
StageReadLoop:
	int 13h					; Invoke BIOS
	jc StageReadLoopPrepare ; Upon error, try again
StageSuccess:
	mov si, messageProgress
	call Print
	jmp 0x1000:0x0000		; Jump to execute sector

start:
	; Setup registers to point to segments
	cli
	mov ax, 0x07c0
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	sti

	mov si, messageWelcome
	call Print

	; Attempt to load stage two, error handling is done in function
	; Read into memory at 0x7c00:0x0200
	xor ax, 0x1000
	mov es, ax			; Load position piece one
	mov bx, 0x0000		; Load position for stage two bootloader (512 bytes)
	call Stage

	; This message is supposed not to appear
	mov si, messageWelcome
	call Print

	; Disable interrupts and halt system
	cli
	hlt

; Data
messageDebug:		; Message used for debugging purposes
	db "$$$", 0
messageWelcome:		; Message when entering the boot part of the multiboot loader
	db "Boot, stage one.", 0ah, 0dh, 0
messageProgress:	; Message upon successfully loading one sector of the stage two bootloader
	db "*", 0

; 510 - (current address - starting address)
; Pad out with blank space
times 510 - ($-$$) db 0

; The magic BIOS bootsector number
; Highly magical
dw 0xaa55
And here is the STAGE 2 (loader.asm):

Code: Select all

; We are still in 16-bit real mode
; We are still in 16-bit real mode
[bits 16]

; Go to program entry point
jmp main

; DEFINE INNER FUNCTIONS
; PRINT STRING
; Function for printing strings
Print:
	mov ah, 0eh		; Used for printing a character to the screen
PrintString:
	lodsb 			; Take the next character (byte) from SI and store in AL
	and al, al		; Pointless operation to check whether or not AL is zero
	jz PrintDone 	; If it is, the print is finished
	int 10h			; Execute
	jmp PrintString ; Carry on printing until zero has been found 
PrintDone:
	ret 			; Return back to from where function was called

; PROGRAM ENTRY
main:
	; FRIENDS, FRIENDS HERE IS THE ERROR
	; FRIENDS, HERE I AM: THE CODE WHO IS NOT BEHAVING
	; PLEASE SAVE ME
	; I AM HERE EVERYBODY!
	; Print a string (NOT WORKING)
	mov si, messageWelcome
	call Print

	; I FOR SOME ODD REASON WORK, EVEN THOUGH I AM PRINTED
	; OUT IN A RATHER SIMILAR WAY TO THAT OF MY BROTHER ABOVE
	; YO
	; Print a "u", which for some odd reason works...
	mov ah, 0eh
	mov al, "u"
	int 10h

	cli
	hlt

; Data
messageWelcome:		; Message when entering the loader part of the multiboot loader, the part before the kernel
	db "Boot, stage two.", 0ah, 0dh, 0

; Boot stage two is a whole lot larger than boot stage one
; Still not too big for our bootloader to handle
; Pad with zeroes
times 512 - ($-$$) db 0		; Final version will be 4096 bytes
I have absolutely nothing against being pointed in the right direction towards solving the problem; if you do not want to, you do not have to tell me the answer straight away. Perhaps you are one of those people who prefer pointing people towards the right solution, rather than telling them straight away. That is completely fine. Whatever you deem best in the way of learning! :D

Thanks a hole lot in advance and thank you for for taking your time reading through all this! Many thanks!

Best regards,

Red Twtty
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: Printing string behaves oddly from loaded disk sector

Post by BrightLight »

In your first stage, try "mov ax, 0x1000" instead of "xor" when loading the sector.
Oh, and you haven't set up a stack in either stage.
In stage two, set up the segment registers:

Code: Select all

main:
mov ax, 0x1000
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
You know your OS is advanced when you stop using the Intel programming guide as a reference.
twtty
Posts: 8
Joined: Wed Feb 10, 2016 6:30 pm

Re: Printing string behaves oddly from loaded disk sector

Post by twtty »

Oh man, I wonder what that xor is doing there... :oops:

As with changing the xor to mov, setting up the segment registers did the trick. Thank you so very much!
twtty
Posts: 8
Joined: Wed Feb 10, 2016 6:30 pm

Re: Printing string behaves oddly from loaded disk sector

Post by twtty »

About not having set up a stack: that is not entirely necessary unless I connect with some higher level language, correct? Or are there any remarkable logical applications of the stack down at bootloader level worth noticing? Before setting up a higher level language, that is.
azblue
Member
Member
Posts: 147
Joined: Sat Feb 27, 2010 8:55 pm

Re: Printing string behaves oddly from loaded disk sector

Post by azblue »

twtty wrote:About not having set up a stack: that is not entirely necessary unless I connect with some higher level language, correct? Or are there any remarkable logical applications of the stack down at bootloader level worth noticing? Before setting up a higher level language, that is.
Hardware interrupts will use the stack, so you want to have it set up right away.

Also, I wanted to point out you never cleared the direction flag; even thought it "works" right now you will inevitably find a computer that it doesn't work on. So throw a CLD command into your code before calling your print function.

Also, look closely at your code for reading a sector: What happens if it keeps failing?
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Printing string behaves oddly from loaded disk sector

Post by kzinti »

twtty wrote:About not having set up a stack: that is not entirely necessary unless I connect with some higher level language, correct? Or are there any remarkable logical applications of the stack down at bootloader level worth noticing? Before setting up a higher level language, that is.
Your own code is using the stack..

hint #1: PrintString
hint #2: int 10h
twtty
Posts: 8
Joined: Wed Feb 10, 2016 6:30 pm

Re: Printing string behaves oddly from loaded disk sector

Post by twtty »

Ah! Thank you everybody for all the responses. I fell sick shortly after posting and have for that reason not gotten back to you. All posts have been very helpful!
Post Reply