Friday, July 27, 2012

Reading Disk Properties in Assembler - INT 13H

This post is a continuation from the previous post [Writting a Bootloader] which was an attempt to build a Bootloader for the x86 architecture.

Although the executable size is limited to 512 Bytes, there are several important tasks that can be accomplished during booting process. One of them is to read the Geometry from several storage devices.

Interrupt 13h [INT 13h] provides sector-based disk access services using the CHS addressing  method (Cylinder/Head/Sectors). This values provide the physical location of the data (although this is not completely true nowadays).

The code below is an example of this interrupt. It reads the CHS from the first Hard Disk using Interrupt 13h.

Briefly, interrupt parameters are set in AX and DX registers. After interrupt is completed, its values can be read from the appropriate registers (CX, DX). The rest of the code includes helper functions to print numbers and strings to present results properly.

After booting our virtual system using the code, we get the following result:

    Hello Again
    Hard Drive Information
    Disk Geometry (C/H/S): 130/16/63

Comparing these results with fdisk on the same drive:


    Disk /dev/sdb: 67 MB, 67108864 bytes
    255 heads, 63 sectors/track, 8 cylinders, total 131072 sectors
    Units = sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk identifier: 0x00000000


I am still trying to figure why these values are so different. Anyway, the total size of the drive taking the total oh Cylinders/Heads/Sectors will be close to the drive size described by fdisk.

Finally, notice that 08h service is limited to drives up to 500 MB. If there's required to read properties from bigger drives, service 48h is the appropriate.

As exercise, following improvements can be done:
  • Report an error if reading fails
  • Read properties from all connected drives
  • Determine drive size in LBA format
  • Modify code to read bigger drives


  1. BITS 16                 ;Tell compiler that this is 16 Bit code
  2. org 07C00h              ;Tell compiler code will be loaded in this memory section
  3.  
  4. mov si, txtStr
  5. call printTxt
  6. call crlf
  7. mov si, txtStr2
  8. call printTxt
  9. call crlf
  10.  
  11. mov si, txtDisk
  12. call printTxt
  13.  
  14. ;Read HD1 parameters
  15. mov AH, 08h     ;Read Drive Parameters
  16. mov DL, 80h     ; First Drive
  17. int 13h
  18.  
  19. push cx
  20. mov ax, cx      ;Cylinders
  21. and ax, 0C0h
  22. shl ax, 2
  23. and cx, 0FF00h
  24. shr cx, 8
  25. or cx, ax
  26. mov ax, cx
  27. inc ax
  28. call printNum
  29. mov si, txtSlash
  30. call printTxt
  31. pop cx
  32.  
  33. mov al, dh      ;Num Heads
  34. mov ah, 0
  35. inc ax
  36. call printNum
  37. mov si, txtSlash
  38. call printTxt
  39.  
  40. and cx, 3Fh ;[5..0] Sectors Per Track
  41. mov ax, cx
  42. call printNum
  43. call crlf
  44.  
  45. JMP $
  46.  
  47. ;********************* Utility Functions ******************
  48.  
  49. printNum:       ;Print a number (ax)
  50.         push cx
  51.         push dx
  52.         mov cx,000Ah    ;divide by 10
  53.         mov bx, sp
  54.         getDigit:
  55.                 mov dx,0        ;puting 0 in the high part of the divided number (DX:AX)
  56.                 div cx          ;DX:AX/cx.  ax=dx:ax/cx  and dx=dx:ax%cx(modulus)
  57.                 push dx
  58.                 cmp ax,0
  59.         jne getDigit
  60.  
  61.         printNmb:
  62.                 pop ax
  63.                 add al, 30h     ;adding the '0' char for printing
  64.                 mov ah,0eh      ;print char interrupt
  65.                 int 10h
  66.                 cmp bx, sp
  67.         jne printNmb
  68.  
  69.         pop dx
  70.         pop cx
  71.         RET
  72.  
  73. printTxt:       ;Print a String (si)
  74.   lodsb
  75.   cmp al, 0
  76.   je exitFn
  77.   mov ah, 0Eh
  78.   int 10h
  79.   jmp printTxt
  80. exitFn:
  81.   RET
  82.  
  83. crlf:   ;Print End of line
  84.         mov ax, 0E0dh
  85.         int 10h
  86.         mov ax, 0E0ah
  87.         int 10h
  88.         RET
  89.  
  90. ;AppData
  91. txtStr db "Hello Again", 0
  92. txtStr2 db "Hard Drive Information", 0
  93. txtDisk db "Disk Geometry (C/H/S): ", 0
  94. txtSlash db "/", 0
  95. times 510-($-$$) db 0   ;Fill the rest of the Loader with "0"
  96. dw 0AA55h               ;Bootloader Signature




1 comment:

Anonymous said...

I found your website through a random stroke of luck. It helped me do my research on this topic. I have spent lots of time looking through your site. You have something good going here, keep it up!