sector number (6 bits, possible values are 1 to 63). Cylinder and Sector bits are numbered below: CX = ---CH--- ---CL--- cylinder : 76543210 98 sector : 543210 Examples of translation: CX := ( ( cylinder and 255 ) shl 8 ) or ( ( cylinder and 768 ) shr 2 ) or sector; cylinder := ( (CX and 0xFF00) shr 8 ) or ( (CX and 0xC0) shl 2) sector := CX and 63; Addressing of Buffer should guarantee that the complete buffer is inside the given segment, i.e. ( BX + size_of_buffer ) <= 10000h. Otherwise the interrupt may fail with some BIOS or hardware versions. Example Assume you want to read 16 sectors (= 2000h bytes) and your buffer starts at memory address 4FF00h. Utilizing memory segmentation, there are different ways to calculate the register values, e.g.: ES = segment = 4F00h BX = offset = 0F00h sum = memory address = 4FF00h would be a good choice because 0F00h + 2000h = 2F00h <= 10000h ES = segment = 4000h BX = offset = FF00h sum = memory address = 4FF00h would not be a good choice because FF00h + 2000h = 11F00h > 10000h Function 02h of interrupt 13h may only read sectors of the first 16,450,560 sectors of your hard drive, to read sectors beyond the 8 GB limit you should use function 42h of Extensions. Another alternate may be DOS interrupt 25h which reads sectors within a partition. Code Example [ORG 7c00h] ; code starts at 7c00h xor ax, ax ; make sure ds is set to 0 mov ds, ax cld ; start putting in values: mov ah, 2h ; int13h function 2 mov al, 63 ; we want to read 63 sectors mov ch, 0 ; from cylinder number 0 mov cl, 2 ; the sector number 2 - second sector (starts from 1, not 0) mov dh, 0 ; head number 0 xor bx, bx mov es, bx ; es should be 0 mov bx, 7e00h ; 512bytes from origin address 7c00h int 13h jmp 7e00h ; jump to the next sector ; to fill this sector and make it bootable: times 510-($-$$) db 0 dw 0AA55h After this code section (which the asm file should start with), you may write code and it will be loaded to memory and executed. Notice how we didn't change dl (the drive). That