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