Omar Mohammad
Omar Mohammad

Reputation: 31

I can't read a sector from a CD-ROM in x86 assembly

I'm trying to load the second stage bootloader from my ISOSYS bootloader for my OS32 operating system, but I can't seem to do it. CF seems to always be set. This is to be booted from a CD/DVD and I'm using Debian GNU/Linux 7.6 (Wheezy)

Here's isosys.asm:

;===============================================================
;
;               ISOSYS v1.0 in isosys.asm
;
; Program for booting OS32 and OS32-based systems from CD/DVDs
; using the ElTorito boot standard.
;
; By Omar, 2014
;
; ===============================================================

; set up bios...
bits 16
org 0x7c00

; beginning of sector 1, byte 0:

; jump over functions block
jmp Start

;
; Print()
;      prints a string to standard output
; AL = 0 : terminate
;

Print:
   lodsb            ; grab a byte from SI and place it in AL
   cmp al, 0         ; is AL = 0?
   jc PrintDone         ; yep, we're done so return
   mov ah, 0eh
   int 0x10         ; nope, print the character
   jmp Print         ; loop until no more characters to be printed
PrintDone:
   ret            ; return to wherever we were!

;
; Start()
;      bootloader entry point
;

Start:
   mov si, creditmsg
   call Print         ; print the first message
   mov dh, 1         ; read 1 sector

.ReadSector:
   cli            ; disable interrupts
   push dx            ; push this stack value
   sti            ; re-enable interrupts

   mov ax, 0x1000         ; read sector into address 0x1000
   xor bx, bx         ; read sector into offset 0x0
   mov ah, 0x02         ; read sector function
   mov al, dh         ; read 1 sector
   mov ch, 0x0         ; must be 0x0 to read sector
   mov dh, 0         ; reading head 0
   mov cl, 0x02         ; start reading from sector 2 to load the second stage

   mov [CDDriveNumber], dl      ; store our drive number is variable CDDriveNumber
   cli            ; disable interrupts
   pusha            ; save the stack
   sti            ; enable interrupts

   int 0x13         ; INT 13h
   jc Error         ; handle error because Carry Flag is set

   pop dx            ; Restore DX

.ExecuteSector:
   ; now that our sector was loaded into address 0x1000:0x0, let's execute it!
   jmp 0x1000:0x0         ; jump to execute the sector
;
; Error()
;      handles errors when carry is set
;

Error:
   mov si, errmsg
   call Print         ; print an error message

   cli            ; disable interrupts to prevent problems
   hlt            ; halt the system... :(

; data section

creditmsg db "ISOSYS v1.0 by Omar Mohammad, Init...", 0
errmsg db "Cannot load the second stage. (File not found maybe?)", 0
CDDriveNumber db 0

times 2048 - ($-$$) db 0      ; fill in 2048 bytes with zeroes

; end of sector 1! :D Any more code here would take bytes 2048 and 2049 but we don't    need that...

This is boot.asm, the second stage:

bits 16
org 0x1000

Main:
   xor bx, bx
   mov ah, 0eh
   mov al, 'A'
   int 0x10

   cli
   hlt

times 2048 - ($-$$) db 0

I compiled with nasm -f bin isosys.asm -o ISOSYS and nasm -f bin boot.asm -o BOOT Then I did mkdir iso and then cp ISOSYS iso/ then cp BOOT iso/ and then generated ISO: genisoimage -no-emul-boot -boot-load-size 4 -eltorito-boot ISOSYS -o boot.iso iso/

I run it in VirtualBox but all it says is Cannot load the second stage (file not found maybe?) which means that Carry Flag is set but I can't seem to find the error.

Any help anyone? Help would be greatly appreciated! :*

Upvotes: 1

Views: 1442

Answers (1)

mirabilos
mirabilos

Reputation: 5347

Your stack handling is totally off. You push dx (why?) inside a clisti block (WHY?), then pusha but don't popa.

You're also missing a mov es,ax after the mov ax, 0x1000 to actually set the segment register to where you want your code to be loaded at.

You cannot read ISOs with the CHS function (AH=02h), you must use the LBA function (AH=42h) with a parameter block. Have an example.

Upvotes: 2

Related Questions