section .bss chsspt: equ 0 ; word sectors per track chsnos: equ 2 ; word number of sides chspo: equ 4 ; dword partition offset chssiz: equ 8 chstab: resw (4*chssiz) section .text ; Convert between drive number and BIOS dl ; Bidirectional mapping ; 0 <-> 0, 1 <-> 1, 2 <-> 0x80, 3 <-> 0x81 dnconv: mov cx, 7 ror dx, 1 rol dl, 1 dncl: rcl dl, 1 rcr dh, 1 loop dncl xchg dh, dl ret fndchs: ; find CHS table entry ; IN dl DOS drive number (A=0, B=1, ...) ; OUT cs:si ptr to chs table entry push ax mov ax, chssiz mul dl add ax, chstab mov si, ax pop ax ret ; compare sector number in disk access packet with zero ; sets zero flag accordingly iszero: push ax mov ax, [bx] or ax, [bx+2] pop ax ret ; calculate CHS from dap and CHS table entry ; IN ds:bx disk access packet ; cs:si chstab table entry ; OUT cx,dh chs data for int 13h calchs: push ax ; load linear sector number mov dx, [bx+2] mov ax, [bx] ; if any word of it is non-zero, we need to do calculation call iszero jz .zero ; ax is track number (lba / spt) ; dx is sector (lba % spt) + 1 div word [cs:si+chsspt] inc dx ; sector number mov cl, dl ; ax is cylinder (track / heads) ; dx is head (track % heads) xor dx, dx div word [cs:si+chsnos] ; set up cylinder and head number mov ch, al mov dh, dl pop ax ret ; set up CHS data for int 13h for reading sector zero .zero: mov cx, 1 ; C=0, S=1 mov dh, 0 ; H=0 pop ax ret ; ABSOLUTE DISK READ / DISK WRITE int25h: mov ah, 2 jmp adisk int26h: mov ah, 3 adisk: push bp push ds push es mov bp, sp cmp cx, 0xFFFF je .islrg ; build a disk access packet on the stack push ds ; dword transfer buffer push bx push cx ; word number of sectors push cs ; dword starting sector number (CS always 0) push dx ; set our freshly created dap as DS:BX mov bx, sp push ss pop ds .islrg: mov dl, al call fndchs call calchs mov dl, al mov al, [bx+4] mov es, [bx+8] mov bx, [bx+6] int 0x13 jc .ret .ret: mov sp, bp pop es pop ds pop bp retf