码迷,mamicode.com
首页 > 其他好文 > 详细

第九天、继续读写软盘

时间:2015-11-07 17:44:58      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:

    今天把读写软盘的代码写完,目标是把跨磁道的读写操作分为若干次单磁道的读写操作。思路是这样的:先把起始扇区所在磁道内的扇区读写完,然后修改输来的参数——去掉已经读写的部分,重新计算起始逻辑扇区号、要读写的扇区数、内存缓冲区地址,这样就可以当做新任务去读写。为了方便测试,把昨天的代码加上输出文字部分一起贴上来:

; ReadWriteFloppyLogicalSectors.nas

; ========================================================================================
[SECTION .data]
    iCylinder dd 0
    iHead     dd 0
    iSector   dd 0
    nSectorsOfThisTrack dd  0   ; 起始扇区所在磁道内要读写的扇区数
    nSectorsOfOpetate   dd  0   ; 实际成功读写的扇区数
    strFormat db ‘ iBeginLogicalSector = %04d, nSectors = %02d, Memory Address = %04d ,Clylinder = %02d, Head = %02d, Sector = %02d‘, 0xa, 0
; ****************************************************************************************

; ========================================================================================
[SECTION .text]
extern _printf
global _ReadWriteFloppyLogicalSectors

; ----------------------------------------------------------------------------------------
; 函数格式:int OPerateOneTrack(int iFunctionNumber,
;                       int iBeginLogicalSector, int nSectors, unsigned char *puchBuffer);
; 函数功能:读写软盘逻辑扇区
; 入口参数:iFunctionNumber =  功能号:02H 读、03H 写
;           iBeginLogicalSecot = 起始逻辑扇区号
;           nSectors = 要读取的扇区个数(需要进行读写的全部扇区必须在同一条磁道内)
;           puchBuffer = 存放数据的内存缓冲区地址
; 返回值:0 = 成功,其他值 = 错误状态代码
_OPerateOneTrack:
    push ebp
    mov ebp, esp
    sub esp, 7 * 4

    ; 计算柱面号:= 逻辑扇区号 div (磁头数 * 每磁道扇区数)
    xor edx, edx
    mov eax, [ebp + 3 * 4]
    mov ebx, 36
    div ebx
    mov [iCylinder], eax

    ; 计算磁头号:= (逻辑扇区号 div 每磁道扇区数) mod 磁头数
    xor edx, edx
    mov eax, [ebp + 3 * 4]
    mov ebx, 18
    div ebx
    xor edx, edx                    ; 只保留商,舍弃余数
    mov ebx, 2
    div ebx
    mov [iHead], edx

    ; 计算扇区号:= (逻辑扇区号 mod 每磁道扇区数) + 1
    xor edx, edx
    mov eax, [ebp + 3 * 4]
    mov ebx, 18
    div ebx
    inc edx
    mov [iSector], edx

    ; 输出计算结果——实际应用的时候须换用调用 int 0x13 的代码
    mov eax, [iSector]
    push eax
    mov eax, [iHead]
    push eax
    mov eax, [iCylinder]
    push eax
    mov eax, [ebp + 5 * 4]
    push eax
    mov eax, [ebp + 4 * 4]
    push eax
    mov eax, [ebp + 3 * 4]
    push eax
    mov eax, strFormat
    push eax
    call _printf
    add esp, 7 * 4

    ; 置返回值
    mov bl, ah
    xor eax, eax
    mov al, bl

    leave
    ret

; ----------------------------------------------------------------------------------------
; 函数格式:int OPerateFloppyLogicalSectors(int iFunctionNumber,
;                       int iBeginLogicalSector, int nSectors, unsigned char *puchBuffer);
; 函数功能:读写软盘逻辑扇区
; 入口参数:iFunctionNumber =  功能号:02H 读、03H 写
;           iBeginLogicalSecot = 起始逻辑扇区号
;           nSectors = 要读写的扇区个数
;           puchBuffer = 存放数据的内存缓冲区地址
; 返回值:eax = 实际成功读写的扇区数
_ReadWriteFloppyLogicalSectors:
    push ebp
    mov ebp, esp
    sub esp, 4 * 4

    ; 检查参数的有效性
Label_CheckParameter:
    mov eax, [ebp + 2 * 4]          ; 2 =< 功能号 =< 3
    cmp eax, 2
    jl Label_Return
    cmp eax, 3
    jg Label_Return

    mov eax, [ebp + 3 * 4]          ; 0 =< 起始逻辑扇区号 =< 2879
    cmp eax, 0
    jl Label_Return
    cmp eax, 2879
    jg Label_Return

    mov ebx, [ebp + 4 * 4]          ; 1 =< 要读写的扇区个数 =< 2880
    cmp ebx, 1
    jl Label_Return
    cmp ebx, 2880
    jg Label_Return

    add ebx, eax                    ; 起始逻辑扇区号 + 要读写的扇区个数 =< 2880
    cmp ebx, 2880
    jg Label_Return

    mov ebx, [ebp + 5 * 4]          ; 内存缓冲区地址 != NULL
    cmp ebx, 0
    je Label_Return

    ; 计算起始扇区所在磁道内剩余可读写的扇区数
    xor edx, edx
    mov ebx, 18                     ; S = ( LBA mod NS ) + 1
    div ebx                         ; 起始逻辑扇区号 / 每磁道扇区数
                                    ;   余数 = 起始逻辑扇区在其所在磁道的扇区号 - 1
    sub ebx, edx                    ; 每磁道扇区数 -(扇区号 - 1)=
                                    ;   起始逻辑扇区所在磁道内,该扇区之后的扇区数(含该扇区)
                                    ;   即起始扇区所在磁道内剩余可读写的扇区数
    ; 剩余可读写扇区数与要读取的扇区数比较
    mov ecx, [ebp + 4 * 4]
    cmp ebx, ecx
    jl Label_Less_1
    mov [nSectorsOfThisTrack], ecx  ;   大于则只读写要读取的扇区个数
    jmp Label_Call_OPerateOneTrack
Label_Less_1:
    mov [nSectorsOfThisTrack], ebx  ;   小于则全部读写完该磁道剩余部分

    ; 把起始扇区所在磁道的要读写的扇区读写完
Label_Call_OPerateOneTrack:
    mov eax, [ebp + 5 * 4]
    push eax
    mov eax, [nSectorsOfThisTrack]
    push eax
    mov eax, [ebp + 3 * 4]
    push eax
    mov eax, [ebp + 2 * 4]
    push eax
    call _OPerateOneTrack
    add esp, 4 * 4

    ; OPerateOneTrack 返回值非 0,说明读写出错
    cmp eax, 0
    jne Label_Return

    ; 累加已成功读写的扇区数
    mov eax, [nSectorsOfThisTrack]
    add [nSectorsOfOpetate], eax

    ; 调整各参数值
    add [ebp + 3 * 4], eax          ; 调整起始逻辑扇区号
    sub [ebp + 4 * 4], eax          ; 调整要读写的扇区个数
    mov ebx, 512
    mul ebx
    add [ebp + 5 * 4], eax          ; 调整内存缓冲区地址

    ; 循环继续读写
    jmp Label_CheckParameter

Label_Return:
    mov eax, [nSectorsOfOpetate]
    leave
    ret
; ****************************************************************************************

    顺手在用 C 语言调用做个测试:

/* test.c */

#include <stdio.h>
#include <stdlib.h>

extern int ReadWriteFloppyLogicalSectors(int iFunctionNumber,
                       int iBeginLogicalSector, int nSectors, unsigned char *puchBuffer);

int main(int argc, int argv[])
{
    int iFunctionNumber = 2, iBeginLogicalSector = 3,  nSectors = 35, nRet = 0;
    unsigned char *puchBuffer;

    puchBuffer = (unsigned char *)malloc(512 * nSectors);
    if(puchBuffer == NULL)
    {
        puts(" 申请内存失败\n");
        return -1;
    }
    printf(" 从软盘逻辑扇区 %04d %s %04d 个扇区的数据存放到内存 %d 处\n",
        iBeginLogicalSector, iFunctionNumber == 2 ? "读" : "写", nSectors, puchBuffer);
    nRet = ReadWriteFloppyLogicalSectors(iFunctionNumber, iBeginLogicalSector, nSectors, puchBuffer);
    free(puchBuffer);

    printf(" 实际读取扇区数: %d\n", nRet);

    return nRet == 0 ? -1 : 0;
}
#MAkeFile

ALL:
	nasm -felf ReadWriteFloppyLogicalSectors.nas
	gcc -o Test Test.c ReadWriteFloppyLogicalSectors.o
CLS:
	del *.o *.exe

   输出结果貌似是对的:

 从软盘逻辑扇区 3 读 35 个扇区的数据存放到内存 4007112 处

 iBeginLogicalSector = 0003, nSectors = 15, Memory Address = 4007112 ,Clylinder = 00, Head = 00, Sector = 04

 iBeginLogicalSector = 0018, nSectors = 18, Memory Address = 4014792 ,Clylinder = 00, Head = 01, Sector = 01

 iBeginLogicalSector = 0036, nSectors = 02, Memory Address = 4024008 ,Clylinder = 01, Head = 00, Sector = 01

 实际读取扇区数: 35


第九天、继续读写软盘

标签:

原文地址:http://my.oschina.net/u/580100/blog/527454

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!