Reputation: 8610
I am trying to learn assembly in real mode .I wanted to read the boot sector of the hard disk ,So below is the code
org 100h
start:
xor ax, ax
mov es, ax ; ES <- 0
mov cx, 1 ; cylinder 0, sector 1
mov dx, 0080h ; DH = 0 (head), drive = 80h (0th hard disk)
mov bx, buff ; segment offset of the buffer
mov ax, 0201h ; AH = 02 (disk read), AL = 01 (number of sectors to read)
int 13h
jnc .read
.read:
mov ax, cs ; set up segments
mov ds, ax
mov es, ax
mov al, 03h
mov ah, 0
int 10h
mov si, buff
call print_string
.done:
jmp .done
print_string:
lodsb ; grab a byte from SI
test al, al ; logical or AL by itself
jz .done ; if the result is zero, get out
mov ah, 0x0E
int 0x10 ; otherwise, print out the character!
jmp print_string
.done:
ret
buff dw 512
My execution environment is DosBox0.70 and exe file is .COM. I am expecting to see 512 bytes on screen but when I run my .COM file its just blank screen there.There are couple of reason that I could see behind it
1)Is given code not returning from Bios interrupt properly(int 13h). 2)String should terminate with null ,which is not happening here.
But not sure is it the above reasons causing it to happen and if so how do I reactify theses issues??
Upvotes: 0
Views: 2674
Reputation: 3119
Dos loads a .com file to some segment of it's own choosing, and sets ds
and es
to that segment. Your buff
is in that segment, not segment 0! You're reading the first sector to segment 0, which probably clobbers your IVT. Leave es
alone.
After reading one sector, you check for carry flag (indicating an error), but drop into .read
whether it's set or not.. If error, you probably want to reset the drive and try the read again. You probably want a "retry counter" around this, so you don't go into an infinite loop.
Your buff
does not reserve 512 bytes, but two bytes with a value of 512. Since it's at the end of your file, this probably won't do any harm, but it isn't "right".
Having successfully read a sector, you could print it as ascii characters, but you want to print all 512 bytes, not stop at the first 0 you encounter. A hex dump would probably be more readable.
If the first byte of your MBR is zero, we're in deep muddy water! The first byte of a valid bootsector should be a short jmp
followed by a nop
, or a near jmp
. We're a bit casual about starting a bootsector that way, and most BIOSes don't check, but that's what's "supposed" to be there. What would the CPU execute if it saw 0 as the first byte? (hint: it's an add
)
I think your two main problems are setting es
to zero, and stopping the print if a zero is encountered. Try it again. FFS, don't try to write anything to your drive until you've got the read working reliably!
Upvotes: 1
Reputation: 7061
The boot sector of the disk contains not ASCII data, but code. With high probability, one of the first bytes will be NULL and remaining possibly not printable codes (such as CR, LF, etc.).
Trying to print the buffer by INT 10h, which prints ascii codes, and ending on 0 will result probably with nothing displayed at all.
You should convert every byte of the buffer to hexadecimal string and then print these strings to the display. This way you will get simple hex dump of the boot sector.
Upvotes: 3