• int 0x13 读取磁盘到内存 Loading Sectors


    link

    Loading Sectors

    by Daniel Rowell Faulkner

    This tutorial is to show you how to load sectors from a floppy disk. Variations will be needed to get this code to work on most other disks.

    In the bootloader code you can use a specific BIOS interrupt to load the sectors from the floppy disk for you. But unfortunatly it addresses the drive in the form of heads, cylinders and sectors.

    Ideally we want to be able to refer to the floppy disk in terms of sectors only (chunks of 512bytes) the code to do that is in the LBA to CHS tutorial. Though to use that you need to first understand this tutorial.

    Explaination of the CHS addressing system:
    CHS simply stands for Cylinder, Head, Sector. This is the addressing system used by the low level BIOS functions and the likes.
    The definitions of each are:
    Sector = Chunk of data on the disk (normally 512bytes) - Segment of a cylinder(aka track)
    Cylinder = This is a track on the disk (normally contains 18sectors)
    Head = Which side of the disk (most floppys now are double sided, 2 heads)

    So sectors 1-18 are on cylinder 1 on head 1 (or track 1 on side 1) but after that it gets complicated sectors 18+ are on varying cylinders and the head number alternates per cylinder.

    This would be better explained with a diagram but that is yet to come I'm afraid though I may include one at a later date.

    Explanation of the interrupt function we will be using:
    We will be using interrupt 0x13 (anything starting in 0x or ending with h is a hexidecimal number)
    Function number passed in ah (Most int's use ah to define a specific function) = 2 (Read sector)
    The values to be passed in the rest of the registers:

    al = Number of sectors to read (To be safe I wouldn't cross the cylinder boundary)
    dh = Head to read from (aka side)	- Addressing registers eg: Town/City
    dl = Drive to read from.		- Country
    ch = Cylinder (aka track) to read from	- Street name
    cl = Sector to read			- House number
    es = Segment to put loaded data into	- Output address in eg: Street name
    bx = Offset to put loaded data into	- House number in the street

    An example to load the first sector of a floppy disk would be:
    ah=2(Function number),al=1(1 sector to read),dh=1(First head)
    dl=0(default for floppy drive),ch=1(First cylinder),cl=1(First sector)
    es=1000h(Put the output at 1000h in memory), bx=0(Offset of 0)

    To get beyound the 18th sector though you would have to change the head and cylinder values as appropriet.

    Example of the code working:

    ; Code to load the second sector on the disk into memory location 0x2000:0x0000
    
    	mov bx, 0x2000	; Segment location to read into (remember can't load direct to segment register)
    	mov es, bx
    	mov bx, 0	; Offset to read into
    	mov ah, 02	; BIOS read sector function
    	mov al, 01	; read one sector
    	mov ch,	01	; Track to read
    	mov cl,	02	; Sector to read
    	mov dh,	01	; Head to read
    	mov dl,	00	; Drive to read
    	int 0x13		; Make the BIOS call (int 13h contains mainly BIOS drive functions)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    I recommend using the LBA to CHS code from one of my other tutorials to get past the cylinder and head addressing problems. In order to use that you put the code into a loop and read one sector at a time like so:
    Get and set output location in memory,get start location,get number of sectors to load.
    Loop 'number of sectors to load' times:
    Run LBA to CHS (to convert the sector number in a head and cylinder)
    Run int 0x13 to load the sector from the LBA to CHS outputed data.
    Increase bx by the number of bytes per sector (512) ready for next sector.

    This code is often best put into a procedure and called as needed to load sectors off a floppy disk.

    A complete example of such a procedure is:

    ; Load kernel procedure
    
    LoadKern:
            mov ah, 0x02    ; Read Disk Sectors
            mov al, 0x01    ; Read one sector only (512 bytes per sector)
            mov ch, 0x00    ; Track 0
            mov cl, 0x02    ; Sector 2
            mov dh, 0x00    ; Head 0
            mov dl, 0x00    ; Drive 0 (Floppy 1) (This can be replaced with the value in BootDrv)
            mov bx, 0x2000  ; Segment 0x2000
            mov es, bx      ;  again remember segments bust be loaded from non immediate data
            mov bx, 0x0000  ; Start of segment - offset value
    .readsector
            int 0x13        ; Call BIOS Read Disk Sectors function
          
            jc .readsector  ; If there was an error, try againz
            mov ax, 0x2000  ; Set the data segment register
            mov ds, ax      ;  to point to the kernel location in memory
    
            jmp 0x2000:0x0000       ; Jump to the kernel
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    A complete example of a procedure including the LBA to CHS code (that procedure is in that tutorial for details on it, though this does use a different version of that procedure):

    ; Procedure ReadSectors - Reads sectors from the disk.
    ;  Input: cx - Number of sectors; ax - Start position
    ;  Output: Loaded file into: es:bx
    
    ReadSectors:
    .MAIN:                          ; Main Label
            mov di, 5               ; Loop 5 times max!!!
    .SECTORLOOP:
            push ax                 ; Save register values on the stack
            push bx
            push cx
            call LBAtoCHS             ; Change the LBA addressing to CHS addressing
            ; The code to read a sector from the floppy drive
            mov ah, 02              ; BIOS read sector function
            mov al, 01              ; read one sector
            mov ch, BYTE [absoluteTrack]    ; Track to read
            mov cl, BYTE [absoluteSector]   ; Sector to read
            mov dh, BYTE [absoluteHead]     ; Head to read
            mov dl, BYTE [BootDrv]          ; Drive to read
            int 0x13                ; Make the BIOS call
            jnc .SUCCESS
            dec di                  ; Decrease the counter
            pop cx                  ; Restore the register values
            pop bx
            pop ax
            jnz .SECTORLOOP         ; Try the command again incase the floppy drive is being annoying
            call ReadError          ; Call the error command in case all else fails
    .SUCCESS
            pop cx                  ; Restore the register values
            pop bx
            pop ax
            add bx, WORD [BytesPerSector]   ; Queue next buffer (Adjust output location so as to not over write the same area again with the next set of data)
            inc ax                          ; Queue next sector (Start at the next sector along from last time)
            ; I think I may add a status bar thing also. A # for each sector loaded or something.
            ; Shouldn't a test for CX go in here???
            dec cx                          ; One less sector left to read
            jz .ENDREAD                     ; Jump to the end of the precedure
            loop .MAIN                      ; Read next sector (Back to the start)
    .ENDREAD:                       ; End of the read procedure
            ret                     ; Return to main program
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    I have loads of variations of this code as I slowly improved it over various versions of my bootloader. I suggest looking at some of my source if you want a more detailed explanation of the source and to see it in context.

    Once you have the data loaded you have to transfer control to it. Now as you should know if you know asm well you can't modify the value in the IP register directly so you have to setup the data segment registers and then jump to the new location.

    The jump command needed is normally:
    jmp :
    eg: jmp 0x1000:0x0000
    Normally for simple kernels you will leave the second part as 0x0000 and the first address should be equal to where you loaded the kernel in memory.

    That is all I have had time to write I am afraid. Not being paid for this :( I will hopefully come back and write this in a more legible form but thats in the future some time.

    All of my examples are cuts and pastes from various versions of my bootloader. Those is probably not ideal examples as I have implemented some things in odd ways. But my bootloaders does work which is the important thing. If you do use any of my code (no matter how small) I would appreciate being notified and my name mentioned with the source next to my code with a link to my website/details. To use any of my code in a commercial product requires my permission however!

    I hope this has helpped you with loading sectors directly.

    If this has helpped you please send me an e-mail saying so. (I like compliments)

    If you want to see new things in here please say, if you want to translate this into an other language please send me the new version so I can host that as an alternative. (I can translate copy's of this if requested but the altavista/google/etc translaters aren't quite perfected for large documents like this, and I would rather spend my time working on something else)



    This tutorial is here with the permission of Daniel Faulkner, if you wish to put this tutorial on another site, please contact Daniel for permission.

  • 相关阅读:
    java实现解数独的算法
    golang chan传递数据的性能开销
    快速掌握jmeter(一)——实现自动登录与动态变量
    【浅谈IDE宏指令录制】为加速chrome扩展国际化,我从vscode回归notepad++
    一文带你精通Git
    免费小程序商城搭建之b2b2c o2o 多商家入驻商城 直播带货商城 电子商务b2b2c o2o 多商家入驻商城 直播带货商城 电子商务
    实时应用程序的 CoreData+CloudKit 集成
    网安周报|OpenSSF 推出恶意软件包存储库
    青少年软件编程C++二级题库(31-40)
    RK3399驱动开发 | 06 - GT911触摸屏驱动调试及驱动浅析(Linux 5.4内核)
  • 原文地址:https://blog.csdn.net/luoganttcc/article/details/126839072