0

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??

Amit Singh Tomar
  • 8,380
  • 27
  • 120
  • 199
  • Try `mov bx, offset buff` – Egor Skriptunoff Jul 17 '13 at 07:42
  • @EgorSkriptunoff: The code looks like it was written for NASM, which doesn't have/need the `offset` keyword. – Michael Jul 17 '13 at 07:45
  • It's quite likely that the boot sector contains bytes that falls outside of the printable range in the ASCII table (and that it contains bytes with the value 0). Instead of using your print_string function, try writing a function that prints each byte as two hexadecimal digits, and repeats this 512 times. Btw, you've declared your buffer as having room for 1024 bytes (512 words). – Michael Jul 17 '13 at 07:50
  • 1
    Version #2: first byte of MBR is zero by some reason. – Egor Skriptunoff Jul 17 '13 at 07:51
  • @EgorSkriptunoff if first byte of MBR is zero then nothing should be printed which is now happeing. – Amit Singh Tomar Jul 17 '13 at 09:01

2 Answers2

3

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.

johnfound
  • 6,857
  • 4
  • 31
  • 60
  • Thanks @johnfound for the your answer ,One thing would like to know if first byte of MBR is zero then can't print it to display using int10h even if its in hexadecimal .is it right ?? – Amit Singh Tomar Jul 17 '13 at 10:26
  • Of course, if you stop to print on byte 0 then yes, but if you want to make hex dump, you must simply print all 512 bytes of the sector. – johnfound Jul 17 '13 at 10:56
  • Johanfound would you like to say anything on Frank comments regarding leaving es to as it is?? – Amit Singh Tomar Jul 17 '13 at 14:30
  • @AmitSinghTomar - Frank is totally right. For .COM program, setting ES and DS to CS is not necessary because they are already set by DOS. You have to set DS or ES only if you want them to point somewhere else. – johnfound Jul 17 '13 at 15:24
1

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!

Frank Kotler
  • 3,079
  • 2
  • 14
  • 9
  • Thanks Frank ,the point you made regarding "you check for carry flag (indicating an error), but drop into .read",The way I am doing is I am checking if my read sector pass through well then it will clear the carry flag and jnc instruction will do a short jump if carry flag is clear ,Am I doing wrong here?? – Amit Singh Tomar Jul 17 '13 at 14:42
  • No, you're okay if carry flag is clear. But if carry flag is set, you still drop through to `.read:`. This isn't going to do any great harm, but your bootsector isn't going to be in `buff`. – Frank Kotler Jul 17 '13 at 14:52
  • Fine Frank ,Got your point .But the point still giving trouble is leaving the es alone(not setting to zero),Could you tell me in greater detail? – Amit Singh Tomar Jul 17 '13 at 14:58
  • `int 13h` reads a sector to a buffer at `es:bx`. Your buffer, `buff` is not in segment 0, but in whatever segment dos loads your file to (and sets `ds` and `es` to). I thought I had an example, but what I can find uses the IDE controller to read the bootsector using ports, instead of BIOS `int 13h`. IDE drives are rare these days, so it isn't going to work. – Frank Kotler Jul 17 '13 at 15:30
  • Thanks @Frank for your kind help ,I will try doing what you suggested and will get back again. – Amit Singh Tomar Jul 17 '13 at 17:15
  • just found this piece of code but not sure how can integrate it to my code http://beyondabstraction.net/school/cs313/proj3/boot.asm – Amit Singh Tomar Jul 17 '13 at 18:34
  • Looks nice! Note that this is a bootsector (which dumps the bootsector), not a .com file. – Frank Kotler Jul 17 '13 at 21:48
  • Yes @Frank ,I have to change the org 0x7c00 to org 0x100 for com files . – Amit Singh Tomar Jul 18 '13 at 07:20