; getgeom.s: tom.viza@gmail.com PUBLIC DOMAIN 2011
; 
; I, Tom Vajzovic, am the author of this software and its documentation and
; permanently abandon all copyright and other intellectual property rights in
; them, including the right to be identified as the author.
; 
; I am fairly certain that this software does what the documentation says it
; does, but I cannot guarantee that it does, or that it does what you think it
; should, and I cannot guarantee that it will not have undesirable side effects.
; 
; You are free to use, modify and distribute this software as you please, but
; you do so at your own risk.  If you remove or hide this warning then you are
; responsible for any problems encountered by people that you make the software
; available to.


; getgeom.s
;
; This is a program to print out the geometry and size of all disks attached
; to an IBM-compatible PC.
;
; It is for 8086 and compatible processors (including i386, amd64 etc). 
;
; It uses PC BIOS function int 13h/AH=08h.  The IBM PC BIOS does not support
; LBA, so is limited to 1024*256*63 sectors (8064.0 MiB).
;
; All output is decimal.  1 MiB is 1024 x 1024 bytes.


org 0x7C00    ; this is a boot sector. set origin                
cli
xor ax,ax
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0x7C00
jmp 0x0000:prestart
prestart:
sti

main:         ; print header, print details of floppy drives then hard drives. never returns
mov si,header
cld
printloop:
lodsb
call print
cmp al,')'
jne printloop
call printnl
mov al,0
call drives
mov al,0x80
call drives
end:
jmp end

drives:       ; print drive details starting with drive number AL. trashes AX,BX,CX,DX,SI,DI,BP
push ax
mov ah,0x08
mov dl,al
int 0x13
jc donedrives
test dl,dl
jz donedrives
pop ax
mov ah,dl
drivesloop:
push ax
call drive
pop ax
inc al
dec ah
jnz drivesloop
donedrives:
ret

drive:          ; print drive number, CHS and size of drive AL and newline. trashes AX,BX,CX,DX,SI,DI,BP and ES with floppies
call get_chs
call convert_chs
mov al,dl
call print3
call printsp
mov ax,si
call print4
call printsp
mov ax,di
call print3
call printsp
mov ax,bp
call print2
call printsp
call printsp
call printsz
call printnl
ret

get_chs:      ; get parameters of drive AL in CX,DH (or zeros on error) and AL in DL. trashes AX,BP and BL,DI,ES with floppies
mov bp,ax
mov ah,0x08
mov dl,al
int 0x13
jnc ok
xor cx,cx
xor dx,dx
ok:
mov ax,bp
mov dl,al
ret

convert_chs:  ; converts end address CX,DX in int13 format to number of C,H,S in SI,DI,BP
mov ax,cx
and ax,0x003F
mov bp,ax     ; sectors per track
mov al,dh
inc ax
mov di,ax     ; tracks per cylinder
mov ah,0
mov al,cl
shl ax,1
shl ax,1
mov al,ch
inc ax
mov si,ax     ; cylinders
ret

printsz:      ; like printf "%04.1f MiB", ((SI * DI * BP) / 2048) with round to nearest. trashes AX BX CX DX SI
mov ax,10
mul si
mov cx,ax
mov dx,di
mov ax,bp
mul dl
mul cx
add ax,0x0400
adc dx,0
mov cx,11
shiftloop:
shr dx,1
rcr ax,1
loop shiftloop
mov cx,10
div cx
mov si,dx
call print4
mov al,'.'
call print
mov ax,si
call printd
call printsp
mov al,'M'
call print
mov al,'i'
call print
mov al,'B'
call print
ret

print4:         ; like printf %04hu AX, AX<=9999.  trashes AX BX CX DH
mov cl,10
div cl
mov dh,ah
call print3
mov al,dh
call printd
ret

print3:         ; like printf %03hhu AL.  trashes AX BX CX
aam
mov cl,al
mov al,ah
call print2
mov al,cl
call printd
ret

print2:         ; like printf %02hhu AL, AL<=99. trashes AX BX CH
aam
mov ch,al
mov al,ah
call printd
mov al,ch
call printd
ret

printnl:        ; print CR LF. trashes AX BX
mov al,0x0D
call print
mov al,0x0A
call print
ret

printsp:        ; print space. trashes AX BX
mov al,0x20
call print
ret

printd:         ; print digit AL, AL<=9. trashes AX BX
add al,0x30
print:          ; print character AL. trashes AX BX
mov ah,0x0E
mov bx,0x0007
int 0x10
ret

header:
dw 'Drv Cyl  Hea Sec Size (all decimal)'

