8086 Bootloader Bug

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
dylankarrdotcom
Posts: 2
Joined: Wed Jun 15, 2011 3:19 pm

8086 Bootloader Bug

Post by dylankarrdotcom »

I'm writing a small operating system for an old Tandy 1100 hd i found in my attic. It only has an 8086 processor, so I'm a little restricted in what assembly instructions I can use, but I've managed to make the simple bootloader/picokernel below. I know it's a stupid idea to put a kernel (or at least its core) in the boot loader, and I know it's a stupid idea to make up my own filesystem instead, but I don't want to hear any complaints about that. I have good reasons for my stupidity, and what I'd really like is just a little help with a bug I've encountered.

On line 98,

Code: Select all

div byte[SectorsPerTrack]
, my code hangs. It doesn't even execute the next line (I tried replacing it with a little int 13h code to write to the screen, but it didn't do anything. It did on the previous line). At first I thought it may be dividing by zero, but if you look at my data section at the top, there's absolutely no way SectorsPerTrack could be zero.

I'm relatively new to assembly. Can anyone tell me what's going wrong?

Code: Select all

[BITS 16]
[ORG 0x07c0]

	jmp short start
	nop

OSLabel				db "DSKOS1.0"
NumberOfFiles		dw 1
NumberOfExtends	dw 0
NumberOfEntries	dw 1
BytesPerSector		dw 512
TotalSectors		dd 2880
TracksPerHead		db 80
SectorsPerTrack	db 18
Heads					dw 2
MediaDescriptor	db 0F0h
SectorOffset		dw 1
DriveNumber			db 0
VolumeLabel			db "DSKOS           "
FileSystem			db "DSKFS1.0"
		
start:
	mov ax, cs								;Setup segments
	mov ds, ax
	mov es, ax
	mov [DriveNumber], dl
	
	cli										;Setup stack
	mov ax, 0
	mov ss, ax
	mov sp, 7BFFh
	sti
	
	mov bx, filelist						;Load filelist intial sector
	mov ax, 1
	call readSector
	
	mov bx, filelist						;Load the rest of the filelist
	xor ax, ax
	mov si, filelist_name
	call getFileInfo
	mov cx, bx
	mov dl, [DriveNumber]
	call loadFileSections

prompt:
	mov ax, 0050h
	mov es, ax
	mov al, ">"
	xor di, di
		
readCharacter:
	push di
	mov ah, 0Ah
	mov bh, 0
	mov cx, 1
	int 10h
	pop di
	
	mov ah, 00h
	int 16h
	
	mov byte[di], al
	inc di
	
	cmp al, 0Dh
	jne readCharacter
	
	dec di
	mov byte[di], 0Ah
	
	mov ax, es
	mov ds, ax
	mov ax, 0000h
	mov si, ax
	
	call getFileInfo
	mov cx, bx
	mov dl, [DriveNumber]
	xor bx, bx
	call loadFileSections
	xor bx, bx
	
	jmp bx

getSectorNumber:							;ax = FileNumber, bx = SectionNumber; returns ax = SectorNumber
	mov cx, ax
	add cx, bx
.loop:
	add ax, cx
	dec cx
	cmp cx, 0
	jne .loop
	add ax, [SectorOffset]
	ret
	
readSector:									;ax = Sector, dl = Drive; reads to es:bx
	div byte[SectorsPerTrack]
	mov cl, ah								;needs later improvement
	and cl, 00111111b
	xor ah, ah
	div byte[TracksPerHead]
	mov ch, ah
	mov dh, al
	mov al, 01h
	mov ah, 02h
	int 13h
	ret
	
getFileInfo:								;si = Filename; returns ax = FileNumber, bx = FileSize, cl = FilePrivelage
	mov bx, filelist
.loop:
	xor cx, cx
	add bx, 4
	push si
	sub si, 1
.cmpstr:
	inc cx
	inc si
	inc bx
	cmp byte[bx], 0Ah
	je .eos
	mov al, byte[bx]
	cmp byte[si], al
	je .cmpstr
.movetoend
	inc bx
	cmp byte[bx], 0Ah
	jne .movetoend
	inc bx
	pop si
	jmp .loop
.eos:
	mov al, byte[bx]
	cmp byte[si], al
	je .found
	pop si
	jmp .loop
.found:
	sub bx, cx
	mov cl, byte[bx]
	sub bx, 4
	mov ax, word [bx]
	add bx, 2
	mov bx, word [bx]
	pop si
	ret
	
loadFileSections:									;ax = FileNumber, cx = FileSize, dl = DriveNumber; reads to es:bx, cx = SectorsRead
	push bx
	mov bx, cx
	call getSectorNumber
	pop bx
	cmp ax, [TotalSectors]
	jg .done
	call readSector
	inc cx
	jmp loadFileSections
.done:
	ret
	
times 510-($-$$) db 0
	db 0x55
	db 0xAA

filelist:
	filelist_number		dw 0
	filelist_size			dw 2
	filelist_privelage	db 0
	filelist_name			db "filelist"
								db 0Ah
								
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: 8086 Bootloader Bug

Post by bluemoon »

Code: Select all

[ORG 0x07c0]
Are you sure the BIOS put you to this instead of 0000:7C00 or 07C0:0000?
Either case your ORG would not be 0x07C0.

So, you are referencing bogus address and until you reached line 98:

Code: Select all

div byte[SectorsPerTrack]
If you're lucky enough that the memory is zero, you may divide by zero;
if you're unlucky (eg after warm boot the memory there may be non-zero), your program goes wild.
dylankarrdotcom
Posts: 2
Joined: Wed Jun 15, 2011 3:19 pm

Re: 8086 Bootloader Bug

Post by dylankarrdotcom »

bluemoon wrote:

Code: Select all

[ORG 0x07c0]
Are you sure the BIOS put you to this instead of 0000:7C00 or 07C0:0000?
Either case your ORG would not be 0x07C0.

So, you are referencing bogus address and until you reached line 98:

Code: Select all

div byte[SectorsPerTrack]
If you're lucky enough that the memory is zero, you may divide by zero;
if you're unlucky (eg after warm boot the memory there may be non-zero), your program goes wild.
wow, i feel stupid. i didn't even notice that. thanks.
Post Reply