second stage bootloader cant access data segments (assembly)

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
User avatar
TwixEmma
Posts: 11
Joined: Tue Jul 16, 2013 10:10 am
Location: England
Contact:

second stage bootloader cant access data segments (assembly)

Post by TwixEmma »

Hi, I hope this is the right place to put my question and that my question hasn't already been asked, I'm not really sure how to describe my problem. I have an OS project that I've been planning and researching for, for the last 7 years. I've made a working HDD bootloader, it loads my second stage loader which is just the following 1024 bytes on the hdd (so the second 2 sectors). I'm using bochs emulator, and fasm for compiling, I intend this to be a wholey asm os, the second stage loader runs in 16bit mode and is intended to setup the hardware as desired and load the kernel (which I have yet to make). the second stage program loads fine, and runs.. but in the second stage program it has a db string at the end that just stores "System Loaded" with a zero byte terminator. It's intended to print this after clearing the screen and setting the cursor position (which all work fine) but it doesn't print the string, it prints some binary from somewhere in memory (this is shown in the image attached below) the code I have is as follows.

G:/system files/ring0/boot/level_one_boot(hdd).asm

Code: Select all

use16
org 0x7C00
;setup registers
xor ax,ax
mov ds,ax
mov es,ax
cli
mov ss,ax
mov sp,0x7C00
sti

;main

call ClearScreen

mov bx,00001101b;purple on black

mov [xpos],4d;xpos
mov [ypos],2d;ypos
call SetCursorPos
mov si,bootstrapname
call PrintText

mov [xpos],4d;xpos
mov [ypos],3d;ypos
call SetCursorPos
mov si,loadingmsg
call PrintText

mov [xpos],0
mov [ypos],5
call SetCursorPos

;begin bootloader
call LoadStage2
cmp [errorflag],0

;check if we successfully loaded the second stage program
jg halt
;if successful, cache the drive number we're loading from and jump to the program
mov dl,80h
push dx
jmp 0x2000:0x0000 ;jump to loaded program

;handle boot failure
halt:
mov bx,00001111b;white on black
mov [xpos],4d;xpos
mov [ypos],5d;ypos
call SetCursorPos
mov si,haltexception
call PrintText

mov [xpos],0
mov [ypos],7
call SetCursorPos

hang:
jmp hang

;routines
ClearScreen:
  pusha
  mov ah,00h
  mov al,03h
  int 10h
  popa
ret

SetCursorPos:;dl = xpos, dh = ypos
  pusha
  mov ah,02h
  mov dl,[xpos]
  mov dh,[ypos]
  int 10h
  popa
ret

PrintText:;si = string start position
  pusha
  mov ah,09h
  mov bh,00h
  mov cx,01h
  .dochar:
    lodsb
    or al,al
    jz .return
    int 10h
    add [xpos],1d
    call SetCursorPos
    jmp .dochar
  .return:
  popa
ret

LoadStage2:
  pusha
  mov bx,0x2000 ;segment
  mov es,bx
  mov bx,0x00   ;offset
  mov [counter1],1
  .tryread:
    mov ah,02h
    mov al,2d
    mov ch,00h
    mov cl,02h
    mov dh,00h
    mov dl,80h
    int 13h
    jc .tryagain
    mov bx,00000101b;purple on black
    mov [xpos],4d;xpos
    mov [ypos],3d;ypos
    call SetCursorPos
    mov si,donemsg
    jmp .fin
  .tryagain:
    add [counter1],1
    cmp [counter1],3
    jg .failed
    jmp .tryread
  .failed:
    mov bx,00000100b;red on black
    mov [xpos],4d;xpos
    mov [ypos],3d;ypos
    call SetCursorPos
    mov si,errormsg
  .fin:
    call PrintText
    mov [xpos],0d;xpos
    mov [ypos],5d;ypos
    call SetCursorPos
  popa
ret

;data section

bootstrapname db "Wolf Bootloader      ",0
loadingmsg db    "Loading System...    ",0
errormsg db      "Failed to Load System",0
donemsg db       "System Loaded...     ",0
haltexception db "Loader Halted!       ",0

xpos db 0
ypos db 0

errorflag db 0
counter1 db 0

;bootloader specifics
times 510-($-$$) db 0
dw 0xAA55
G:/system files/ring0/boot/level_two_boot.asm

Code: Select all

use16
org 0x0000

;retrieve active drive number, assuming the first bootloader cached it for us
pop dx
mov [drivenumber],dl
xor dx,dx

;reset registers
xor ax,ax
mov ds,ax
mov es,ax
cli
mov ss,ax
mov sp,0x2000
sti

;main
call ClearScreen

mov bx,00000101b;purple on black

mov [xpos],4d;xpos
mov [ypos],2d;ypos
call SetCursorPos
mov si,loadedmsg
call PrintText
mov [xpos],0d;xpos
mov [ypos],5d;ypos
call SetCursorPos

halt:
jmp halt

ClearScreen:
  pusha
  mov ah,00h
  mov al,03h
  int 10h
  popa
ret

SetCursorPos:;dl = xpos, dh = ypos
  pusha
  mov ah,02h
  mov dl,[xpos]
  mov dh,[ypos]
  int 10h
  popa
ret

PrintText:;si = string start position
  pusha
  mov ah,09h
  mov bh,00h
  mov cx,01h
  .dochar:
    lodsb
    or al,al
    jz .return
    int 10h
    add [xpos],1d
    call SetCursorPos
    jmp .dochar
  .return:
  popa
ret

loadedmsg db "System Loaded",0

xpos db 0
ypos db 0
drivenumber db 80h ;edit: was dw, should be db (an error when pasting)

times 1024-($-$$) db 0
I apologize if this has already been answered, it seems to work except for the print routine not printing what it's supposed to.
My guess is an addressing problem but I can't find it.
As for the screenshot the characters it's printing out it's almost like the computer is showing a confused emoticon... lol

Screenshot:
Attachments
stage2bootloader01.png
Last edited by TwixEmma on Tue Jul 16, 2013 1:10 pm, edited 1 time in total.
Mikemk
Member
Member
Posts: 409
Joined: Sat Oct 22, 2011 12:27 pm

Re: second stage bootloader cant access data segments (assem

Post by Mikemk »

For anyone unable to view that image,
stage2bootloader01.png
Next time put it as an attachment, or learn to hotlink.
Programming is 80% Math, 20% Grammar, and 10% Creativity <--- Do not make fun of my joke!
If you're new, check this out.
Casm
Member
Member
Posts: 221
Joined: Sun Oct 17, 2010 2:21 pm
Location: United Kingdom

Re: second stage bootloader cant access data segments (assem

Post by Casm »

mov [xpos],4d;xpos
mov [ypos],3d;ypos
call SetCursorPos
Assuming you are using a 80*25 screen, the above will take the cursor right off of the screen. When you are moving the cursor you can forget about the attribute bytes, and just treat it as a 2,000 byte buffer.

If you used int 10h, ah = 0eh instead, you wouldn't have to worry about the cursor anyway, because the BIOS would move it for you.
User avatar
Minoto
Member
Member
Posts: 89
Joined: Thu May 12, 2011 7:24 pm

Re: second stage bootloader cant access data segments (assem

Post by Minoto »

TwixEmma wrote: G:/system files/ring0/boot/level_two_boot.asm

Code: Select all

use16
org 0x0000

;retrieve active drive number, assuming the first bootloader cached it for us
pop dx
mov [drivenumber],dl
xor dx,dx

;reset registers
xor ax,ax
mov ds,ax[/quote]
Why are you setting DS to 0, when your second stage, which contains the message you're trying to print, is loaded at 0x2000:0000?
Those who understand Unix are doomed to copy it, poorly.
User avatar
TwixEmma
Posts: 11
Joined: Tue Jul 16, 2013 10:10 am
Location: England
Contact:

Re: second stage bootloader cant access data segments (assem

Post by TwixEmma »

Thank you all for your replies, the setcursorpos function works fine, there's nothing wrong with that but thank you anyway. as for setting ds to zero I copy pasted from the first stage bootloader, and forgot to take it out. I now have a working split bootloader setup. I load the first stage bootloader, then move it in memory to a lower section of memory, then I run the rest of the loader which loads the second stage to a loadpoint label in the first stage loader, then jumps to it, this works great. I can build the second part in the same asm file and it can also use parts from the first loader for printing text and clearing the screen etc.. I now just need to make the second stage part setup the hardware and load the kernel. Thanks for your help anyway. Here's the new code for anyone interested:

G:/system files/ring0/boot/hdd/bootloader.asm

Code: Select all

;stage 1 boot
use16
org 0x7C00
real_start:
cld
cli
sub ax, ax
mov ds, ax
mov bp, 0x7C00

mov ax, 0x1FE0
mov es, ax
mov si, bp
mov di, bp
mov cx, 0x0100
rep movsw              ;move boot code to the 0x1FE0:0x0000
jmp 0x1FE0:cont

loadseg_off dw 0
loadseg_seg dw 0x0060

cont:
mov ds,ax
mov ss,ax
lea sp,[bp-0x20]
sti
mov [drive],dl ;BIOS passes drive number in DL

main:

call ClearScreen

mov bx,00001101b;purple on black

mov [xpos],4d;xpos
mov [ypos],2d;ypos
call SetCursorPos
mov si,bootstrapname
call PrintText

mov [xpos],4d;xpos
mov [ypos],3d;ypos
call SetCursorPos
mov si,loadingmsg
call PrintText

mov [xpos],0
mov [ypos],5
call SetCursorPos

call LoadStage2
cmp [errorflag],0

jg halt
;jmp testinstead
jmp loadpoint ;jump to loaded program

halt:
mov bx,00001111b;white on black
mov [xpos],4d;xpos
mov [ypos],5d;ypos
call SetCursorPos
mov si,haltexception
call PrintText

mov [xpos],0
mov [ypos],7
call SetCursorPos

testinstead:
mov bx,00001111b;white on black
mov [xpos],4d;xpos
mov [ypos],5d;ypos
call SetCursorPos
mov si,testexception
call PrintText

mov [xpos],0
mov [ypos],7
call SetCursorPos

hang:
xor ah,ah
int 0x16             ; wait for a key
int 0x19             ; reboot the machine

ClearScreen:
  pusha
  mov ah,00h
  mov al,03h
  int 10h
  popa
ret

SetCursorPos:;dl = xpos, dh = ypos
  pusha
  mov ah,02h
  mov dl,[xpos]
  mov dh,[ypos]
  int 10h
  popa
ret

PrintText:;si = string start position
  pusha
  mov ah,09h
  mov bh,00h
  mov cx,01h
  .dochar:
    lodsb
    or al,al
    jz .return
    int 10h
    add [xpos],1d
    call SetCursorPos
    jmp .dochar
  .return:
  popa
ret

LoadStage2:
  pusha
  mov [counter1],1
  .tryread:
    mov ax,ds
    mov es,ax
    mov bx,loadpoint ;offset
    mov ah,02h       ;read sectors into memory
    mov al,4d        ;load 4 sectors
    mov ch,00h       ;the track to read from
    mov cl,02h       ;sector id
    mov dh,00h       ;head
    mov dl,[drive]   ;drive
    int 13h
    jc .tryagain
    mov bx,00000101b;purple on black
    mov [xpos],4d;xpos
    mov [ypos],3d;ypos
    call SetCursorPos
    mov si,donemsg
    jmp .fin
  .tryagain:
    add [counter1],1
    cmp [counter1],3
    jg .failed
    jmp .tryread
  .failed:
    mov bx,00000100b;red on black
    mov [xpos],4d;xpos
    mov [ypos],3d;ypos
    call SetCursorPos
    mov si,errormsg
  .fin:
    call PrintText
    mov [xpos],0d;xpos
    mov [ypos],5d;ypos
    call SetCursorPos
  popa
ret

bootstrapname db "Wolf Bootloader      ",0
loadingmsg db    "Loading System...    ",0
errormsg db      "Failed to Load System",0
donemsg db       "System Loaded...     ",0
haltexception db "Loader Halted!       ",0
testexception db "Loader Tested!       ",0

times 510-($-$$) db 0
dw 0xAA55
;end of stage 1 boot
;=========================================
;stage 2 boot
loadpoint: call ClearScreen

mov bx,00000101b;purple on black

mov [xpos],4d;xpos
mov [ypos],2d;ypos
call SetCursorPos
mov si,loadedmsg
call PrintText
mov [xpos],0d;xpos
mov [ypos],5d;ypos
call SetCursorPos

jmp hang

loadedmsg db "System Loaded",0

;data section

;these will be located in memory after where the second part of the bootloader is loaded to, exactly at the end of it

xpos db 0
ypos db 0

errorflag db 0
counter1 db 0

drive db 0

times 2560-($-$$) db 0;pad out 2048b on top of the bootsector (4 additional sectors)
;end of stage 2 boot
now to code the second loader and the kernel :D

edit: I want to use int 10h ah=09h because it prints in color, teletype doesn't always print in color. :S
Post Reply