je <tag> ; jump when equal jne <tag> ; jump when not equal jz <tag> ; jump when last result was zero jg <tag> ; jump when greater than jge <tag> ; jump when greater than or equal to jl <tag> ; jump when less than jle <tag> ; jump when less than or equal to
; Print something movax, 0xB800 movgs, ax; Set video segment as 0xB800
movsi, 0; Current character index print: movdl, byte [_msg + si] ; Fetch character cmpdl, 0; Exit if character is '\0' je print_exit incsi; index += 1 ; Calculate cordinate in vga memory ; Shift = 2 * (80 * row + col) movax, word [_row] imulax, 80 addax, word [_col] imulax, 2 ; Copy character to memory movbx, ax movbyte [gs:bx], dl; Character to be printed movbyte [gs:bx + 1], 0x0F; Black background with white foreground ; Set new cordinate addword [_col], 1 movax, word [_col] cmpax, 80 jne add_row_exit addword [_row], 1; move cursor to next row if col == 80 movword [_col], 0 add_row_exit: ; Reture to top jmp print print_exit:
; Print something movax, 0xB800 movgs, ax; Set video segment
movsi, 0 print: movdl, byte [_msg + si] cmpdl, 0 je print_exit incsi ; Calculate cordinate in vga memory movax, word [_row] imulax, 80 addax, word [_col] imulax, 2 ; Copy character to memory movbx, ax movbyte [gs:bx], dl; Character to be printed movbyte [gs:bx + 1], 0x0F; Black background with white foreground ; Set new cordinate addword [_col], 1 movax, word [_col] cmpax, 80 jne add_row_exit addword [_row], 1 movword [_col], 0 add_row_exit: ; Reture to top jmp print print_exit:
; Print something movax, 0xB800 movgs, ax; Set video segment
movsi, 0 print: movdl, byte [_msg + si] cmpdl, 0 je print_exit incsi ; Calculate cordinate in vga memory movax, word [_row] imulax, 80 addax, word [_col] imulax, 2 ; Copy character to memory movbx, ax movbyte [gs:bx], dl; Character to be printed movbyte [gs:bx + 1], 0x0F; Black background with white foreground ; Set new cordinate addword [_col], 1 movax, word [_col] cmpax, 80 jne add_row_exit addword [_row], 1 movword [_col], 0 add_row_exit: ; Reture to top jmp print print_exit:
; The following code is public domain licensed [bits16] ; Function: check_a20 ; ; Purpose: to check the status of the a20 line in a completely self-contained state-preserving way. ; The function can be modified as necessary by removing push's at the beginning and their ; respective pop's at the end if complete self-containment is not required. ; ; Returns: 0 in ax if the a20 line is disabled (memory wraps around) ; 1 in ax if the a20 line is enabled (memory does not wrap around) check_a20: pushf pushds pushes pushdi pushsi cli; Disable interrupt ; Save state---------- xorax, ax; ax = 0 moves, ax notax; ax = 0xFFFF movds, ax movdi, 0x0500 movsi, 0x0510 moval, byte [es:di] pushax moval, byte [ds:si] pushax ; End save state-------
; Main code------------ movbyte [es:di], 0x00 movbyte [ds:si], 0xFF; If trunc, the addr should be (0xFFFF0 + 0x510) & 0xFFFFF = 0x500 otherwise should be 0x100500 cmpbyte [es:di], 0xFF ; End main code--------
; Restore state-------- popax movbyte [ds:si], al popax movbyte [es:di], al movax, 0 je check_a20__exit movax, 1 check_a20__exit: popsi popdi popes popds popf ret
在之后的代码中还会用到一些通用的常数值和一些常用的类别如unsigned int、unsigned char和unsigned long long和它们的别名uint32、uint8和uint64等等,可以将它们编写到头文件constants.h和types.h中。由于它们同样可以视为操作系统库的一部分,所以可以放在lib中叫做common的文件夹下
查看Linux关于指令的手册:
+如果想要知道关于某一程序参数的具体描述,可以使用man命令
+例如,man gcc可以查看关于gcc所有参数的描述和用法,其中关于-E参数就有如下描述:
+-E Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which is sent to the standard output.
注:
+首扇区并不是所有的内容都属于BPB结构体的范畴,在后续的介绍中,以 BPB_ 开头的域才是属于BPB结构体的域
+In the following description, all the fields whose names start with BPB_ are part of the BPB. All the fields whose names start with BS_ are part of the boot sector and not really part of the BPB.
//Read the first sector of the volume into buffer //@param {uint32} bpbFrstSec : The first sector of the bpb region FATBPB::FATBPB(uint32 bpbFrstSec) { HDDManager().readSector(bpbFrstSec, 1, _data); }
//Returns count of bytes per sector of the disk //@return {uint16} : following values: 512, 1024, 2048 or 4096 uint16 FATBPB::bytesPerSector(){ return *(uint16*)(&_data[11]); }
//Returns number of sectors per allocation unit //@return {uint8} : A power of 2 that is greater than 0. // Legal values are 1, 2, 4, 8, 16, 32, 64 and 128 uint8 FATBPB::sectorsPerCluster(){ return _data[13]; }
//Returns sectors per track for interrupt 0x13. //This is only relevant for media that have a geometry and are visible //on interrupt 0x13 //@return {uint16} : sectors per track of the media uint16 FATBPB::sectorsPerTrack(){ return *(uint16*)(&_data[24]); }
//Returns the number of heads of the media for interrupt 0x13. //This is only relevant as discussed earlier for [sectorsPerTrack()] //@return {uint32} : One based number for number of heads // For example, on a 1.44MB 3.5-inch floppy drive this // value is 2 uint16 FATBPB::headCount(){ return *(uint16*)(&_data[26]); }
//Returns the number of reserved sectors in the reserved region of the volume //starting at the first sector of the volume, which is also the size of bios //parameter block in sectors //@return {uint16} : Non-zero value of the number of reserved sectors uint16 FATBPB::reservedSectorCount(){ return *(uint16*)(&_data[14]); }
//Returns the count of hidden sectors preceding the partition that contains //this FAT volume. This method is generally only relevant for media visible //on interrupt 0x13 //@return {uint32} : The sectors preceding the partition uint32 FATBPB::hiddenSectorCount(){ return *(uint32*)(&_data[28]); }
//Returns the 32-bit total count of sectors on the volume. The count includes //the count of all sectors in all four regions of the volume //@return {uint32} : The total count of sectors uint32 FATBPB::totalSectors(){ //It should be noted that for volumes that contain more than or equal to 0x10000 //sectors, BPB_TotalSec32 field is used to store the total sectors count. In other //circumstances, BPB_TotalSec16 field is used to store the total sectors count // //In addition, BPB_TotalSec32 field should only be considered valid if BPB_TotalSec16 //is zero return *(uint16*)(&_data[19]) == 0 ? *(uint32*)(&_data[32]) : (uint32)(*(uint16*)(&_data[19])); }
//Returns the count of file allocation tables (FATs) on the volume //@return {uint8} : The count of FATs. A value of 2 is recommended although 1 is acceptable uint8 FATBPB::fatCount(){ return _data[16]; }
//Returns the 32-bit count of sectors occupied by one FAT //@return {uint32} : The sectors occupied by one FAT uint32 FATBPB::fatSize(){ //It should be noted that for FAT12/FAT16 volumes the sectors occupied by one FAT //is stored in 16-bit BPB_FATSz16 field while for FAT32 volumes the value is stored //in 32-bit BPB_FATSz32 field. uint32 fatSz16 = (uint32)(*(uint16*)(&_data[22])); if(fatSz16 != 0) { return fatSz16; } else { return *(uint32*)(&_data[36]); } }
//Returns the active FAT on the volume //It should be noted that this method is FAT32 only //@return {uint8} : Zero-based number of active FAT, only valid if mirroring is disabled uint8 FATBPB::activeFAT(){ return _data[40] & 0xF; }
//Returns whether mirroring is disabled on the volume //It should be noted that this method is FAT32 only //@return {bool} : True means the FAT is morrored at runtime into all FATs. // False means only one FAT is active, it is the one referenced by // [activeFAT()] boolFATBPB::isFATMirrored(){ return (_data[40] & 0x80) != 0; }
//Returns the count of 32-byte directory entries in the root directory //@return {uint16} : The count of directory entries in the root directory. // This value should always specify a count that when multiplied // by 32 results in an even multiple of [bytesPerSecter()] uint16 FATBPB::rootEntryCount(){ return *(uint16*)(&_data[17]); }
//Returns the cluster number of the first cluster of the root directory //It should be noted that this method is FAT32 only //@return {uint32} : the root cluster number uint32 FATBPB::rootCluster(){ return *(uint32*)(&_data[44]); }
//Returns the OEM name identifier in the bios parameter block //@return {char*} : The pointer to the field containing the OEM name in the buffer char* FATBPB::oemName(){ return (char*)(&_data[3]); }
//Returns the media type //@return {uint8} : Legal values are 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE and 0xFF // 0xF8 is standard value for fixed media while 0xF0 is for removable media uint8 FATBPB::mediaType(){ return _data[21]; }
//Returns the drive number for interrupt 0x13 //@return {uint8} : 0x80 or 0x00 uint8 FATBPB::driveNumber(){ //It should be noted that the field containing the value has different offset on FAT12/16 //volumes and FAT32 volumes //On FAT12/16 volumes the field has an offset of 36 while on FAT32 volumes has an offset //of 64 if(isFAT32()) { return _data[64]; } else { return _data[36]; } }
//Check whether the volume contains the extended boot signature which indicates //the BS_VolOD, BS_VolLab and BS_FilSysType fields are present //@return {bool} : Ture for the extended boot signature value is set to 0x29 boolFATBPB::hasExtendedBootSignature(){ //It should be noted that the field containing the value has different offset on FAT12/16 //volumes and FAT32 volumes //On FAT12/16 volumes the field has an offset of 38 while on FAT32 volumes has an offset //of 66 if(isFAT32()) { return _data[66] == 0x29; } else { return _data[38] == 0x29; } }
//Returns the volume serial number for volume tracking on removable media. //It should be noted that this value is only present when [hasExtendedBootSignature()] //function returns a true value. //@return {uint32} : Volume serial number uint32 FATBPB::volumeSerialNumber(){ //It should be noted that the field containing the value has different offset on FAT12/16 //volumes and FAT32 volumes //On FAT12/16 volumes the field has an offset of 39 while on FAT32 volumes has an offset //of 67 if(isFAT32()) { return *(uint32*)(&_data[67]); } else { return *(uint32*)(&_data[39]); } }
//Returns the volume label //@return {char*} : The pointer of the volume label stored in the buffer char* FATBPB::volumeLabel(){ //It should be noted that the field containing the value has different offset on FAT12/16 //volumes and FAT32 volumes //On FAT12/16 volumes the field has an offset of 43 while on FAT32 volumes has an offset //of 71 if(isFAT32()) { return (char*)(&_data[71]); } else { return (char*)(&_data[43]); } }
//Returns the file system type string //@return {char*} : The pointer of the fs type string, the string should be one of the // strings: "FAT", "FAT12", "FAT16" or "FAT32" char* FATBPB::fsTypeLabel(){ //It should be noted that the field containing the value has different offset on FAT12/16 //volumes and FAT32 volumes //On FAT12/16 volumes the field has an offset of 54 while on FAT32 volumes has an offset //of 82 if(isFAT32()) { return (char*)(&_data[82]); } else { return (char*)(&_data[54]); } }
//Returns the sector number of FSINFO structure in the reserved area of the FAT32 volume. //It should be noted that this method is only available on FAT32 volumes. //@return {uint16} : FSINFO structure sector number, usually 1 uint16 FATBPB::fsInfoSector(){ return *(uint16*)(&_data[48]); }
//Check whether the volume is FAT12 boolFATBPB::isFAT12(){ uint32 totClus = totalClusters(); return totClus < 4085; }
//Check whether the volume is FAT16 boolFATBPB::isFAT16(){ uint32 totClus = totalClusters(); return totClus >= 4085 && totClus < 65525; }
//Check whether the volume is FAT32 boolFATBPB::isFAT32(){ uint32 totClus = totalClusters(); return totClus >= 65525; }
//Return the size in bytes of a fat entry //@return {uint32} : 12 for FAT12, 16 for FAT16, 32 for FAT32 uint32 FATBPB::fatEntrySize(){ uint32 totClus = totalClusters(); if(totClus < 4085) { return12; } elseif(totClus < 65525) { return16; } else { return32; } }
//Returns the first sector of first FAT uint32 FATBPB::fatFrstSec(){ returnreservedSectorCount(); }
//Returns the ABSOLUTE sector number of first FAT uint32 FATBPB::fatFrstSecAbsolute(){ returnhiddenSectorCount() + reservedSectorCount(); }
//Returns the total sectors of FATs uint32 FATBPB::fatTotalSec(){ returnfatCount() * fatSize(); }
//Returns the first sector of the root directory region uint32 FATBPB::rootDirFrstSec(){ uint32 resvdSecCnt = reservedSectorCount(); uint32 fatSecCnt = fatTotalSec(); return resvdSecCnt + fatSecCnt; }
//Returns the ABSOLUTE sector number of the first sector of the root //directory region uint32 FATBPB::rootDirFrstSecAbsolute(){ uint32 resvdSecCnt = reservedSectorCount(); uint32 fatSecCnt = fatTotalSec(); uint32 hiddenSec = hiddenSectorCount(); return hiddenSec + resvdSecCnt + fatSecCnt; }
//Returns the total sectors of root directory region uint32 FATBPB::rootDirTotalSec(){ uint32 rootEntCnt = rootEntryCount(); uint32 bytsPerSec = bytesPerSector(); return (rootEntCnt * 32 + (bytsPerSec - 1)) / bytsPerSec; }
//Returns the first sector of data region uint32 FATBPB::dataFrstSec(){ uint32 resvdSecCnt = reservedSectorCount(); uint32 fatSecCnt = fatTotalSec(); uint32 rootSecCnt = rootDirTotalSec(); return resvdSecCnt + fatSecCnt + rootSecCnt; }
//Returns the ABSOLUTE sector number of data region uint32 FATBPB::dataFrstSecAbsolute(){ uint32 resvdSecCnt = reservedSectorCount(); uint32 fatSecCnt = fatTotalSec(); uint32 rootSecCnt = rootDirTotalSec(); uint32 hiddenSec = hiddenSectorCount(); return hiddenSec + resvdSecCnt + fatSecCnt + rootSecCnt; }
//Returns the total sectors of data region uint32 FATBPB::dataTotalSec(){ uint32 totSec = totalSectors(); uint32 resvdSecCnt = reservedSectorCount(); uint32 fatSecCnt = fatTotalSec(); uint32 rootSecCnt = rootDirTotalSec(); return totSec - (resvdSecCnt + fatSecCnt + rootSecCnt); }
//Returns the total clusters of data region uint32 FATBPB::totalClusters(){ returndataTotalSec() / sectorsPerCluster(); }
//Returns the sector of the given cluster //@param {uint32} clus : The zero-based cluster number //@return {uint32} : The sector number of the cluster uint32 FATBPB::secOfCluster(uint32 clus){ uint32 frstDataSec = dataFrstSec(); uint32 clusterOffset = clus - 2; uint32 secPerClus = sectorsPerCluster(); return frstDataSec + clusterOffset * secPerClus; }
//Returns the ABSOLUTE sector of the given cluster //@param {uint32} clus : The zero-based cluster number //@return {uint32} : The absolute sector number of the cluster uint32 FATBPB::absoluteSecOfCluster(uint32 clus){ uint32 frstDataSec = dataFrstSec(); uint32 clusterOffset = clus - 2; uint32 secPerClus = sectorsPerCluster(); uint32 hiddenSec = hiddenSectorCount(); return hiddenSec + frstDataSec + clusterOffset * secPerClus; }
//Calculate/Return the checksum of the entry //It should be noted that this function BEHAVE DIFFERENTLY in SFN and LFN entries //@return {uint32} : Calculate checksum out of filename in SFN entries //@return {uint32} : Return checksum in LFN entries uint32 DirEntry::checkSum(){ if(isSFNEntry()) { //ChkSum() //Returns an unsigned byte checksum computed on an unsigned byte //array. The array must be 11 bytes long and is assumed to contain //a name stored in the format of a MS-DOS directory entry
//The following method is copied from Microsoft FAT specification //page 32, chapter 7.2 Checksum generation byte* pName = &_data[0]; uint16 nameLen; uint8 sum; sum = 0; for(nameLen = 11; nameLen != 0; nameLen--) { //NOTE: The operation is an unsigned char rotate right sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + *pName++; } return sum; } else { //According to Microsoft FAT specification: //The checksum in LFN entries is stored in LDIR_Chksum field //which has an offset of 13 and size of 1 byte return _data[13]; } }
//Check whether the entry is empty //@return {bool} : True for the entry IS empty while False for the opposite boolDirEntry::isEmpty(){ //According to Microsoft FAT specification: //DIR_Name[0] = 0xE5 indicates the directory entry is free //DIR_Name[0] = 0x00 indicates the directory entry and all directory entries following the current free entry are free //Since 0xE5 would never appear in LFN entries, therefore 0xE5 and 0x00 are unique signatures for empty entries return _data[0] == 0xE5 || _data[0] == 0x00; }
//Check whether the entry is a short filename entry //@return {bool} : True for the entry IS a short filename entry while False for the opposite boolDirEntry::isSFNEntry(){ //According to Microsoft FAT specification: //DIR_Attr field indicates whether the entry is a long filename entry //READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID indicates a long filename entry return !attributes().contains( DirectoryFlag::READ_ONLY | DirectoryFlag::HIDDEN | DirectoryFlag::SYSTEM | DirectoryFlag::VOLUME_ID ); }
//Check whether the entry is a long filename entry //@return {bool} : True for the entry IS a long filename entry while False for the opposite boolDirEntry::isLFNEntry(){ //According to Microsoft FAT specification: //DIR_Attr field indicates whether the entry is a long filename entry //READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID indicates a long filename entry returnattributes().contains( DirectoryFlag::READ_ONLY | DirectoryFlag::HIDDEN | DirectoryFlag::SYSTEM | DirectoryFlag::VOLUME_ID ); }
//Check whether the entry is the last member in the lfn entry set //@return {bool} : True for the entry IS the last member in the set while False for the opposite boolDirEntry::isLastInSet(){ //According to Microsoft FAT specification: //The last long directory name entry in the set is masked with 0x40 in the LDIR_Ord field return (_data[0] & LAST_LONG_ENTRY) != 0; }
//Return the DIR_Attr field in the entry //@return {DirectoryFlag} : The attributes of the entry in DirectoryFlag format DirectoryFlag DirEntry::attributes(){ //According to Microsoft FAT specification: //DIR_Attr field has an offset of 11 and size of 1 byte returnDirectoryFlag(_data[11]); }
//Return the creation time of the file/directory in FATTime format //It should be noted that only SFN entries hold this field //@return {FATTime} : The creation time, including hour, minute, second and millisecond FATTime DirEntry::createTime(){ //According to Microsoft FAT specification: //DIR_CrtTimeTenth has an offset of 13 and size of 1 byte //DIR_CrtTime has an offset of 14 and size of 2 bytes returnFATTime(_data[13], *(uint16*)(&_data[14])); }
//Return the creation date of the file/directory in FATDate format //It should be noted that only SFN entries hold this field //@return {FATDate} : The creation date, including year, month and day FATDate DirEntry::createDate(){ //According to Microsoft FAT specification //DIR_CrtDate has an offset of 16 and size of 2 bytes returnFATDate(*(uint16*)(&_data[16])); }
//Return the last accessed date of the file/directory in FATDate format //It should be noted that only SFN entries hold this field //@return {FATDate} : The last accessed date, including year, month and day FATDate DirEntry::lastAccessedDate(){ //According to Microsoft FAT specification //DIR_LstAccDate has an offset of 18 and size of 2 bytes returnFATDate(*(uint16*)(&_data[18])); }
//Return the last modification time of the file/directory in FATTime format //It should be noted that only SFN entries hold this field //@return {FATTime} : The last modification time, including hour, minute, second and millisecond FATTime DirEntry::lastModifiedTime(){ //According to Microsoft FAT specification //Last modification time is stored in DIR_WrtTime field //DIR_WrtTime has an offset of 22 and size of 2 bytes //It should be noted that last modification time does not provide granularity under 2 seconds //More specifically, there is no timetenth field for last modification time returnFATTime(0, *(uint16*)(&_data[22])); }
//Return the last modification date of the file/directory in FATDate format //It should be noted that only SFN entries hold this field //@return {FATDate} : The last modification date, including year, month and day FATDate DirEntry::lastModifiedDate(){ //According to Microsoft FAT specification //Last modification date is stored in DIR_WrtDate field //DIR_WrtDate has an offset of 24 and size of 2 bytes returnFATDate(*(uint16*)(&_data[24])); }
//Return the first cluster of the file/directory //It should be noted that only SFN entries hold this field //@return {uint32} : The first cluster of the file/directory uint32 DirEntry::firstCluster(){ //According to Microsoft FAT specification //first cluster is defined in DIR_FstClusHI and DIR_FstClusLO //This function simply concatenates the high and low bits and returns uint16 frstClusterHI = *(uint16*)(&_data[20]); uint16 frstClusterLO = *(uint16*)(&_data[26]); uint32 frstCluster = ((uint32)frstClusterHI << 16) | frstClusterLO; return frstCluster; }
//Return the size of the file/directory //It should be noted that only SFN entries hold this field //@return {uint32} : The size of the file/directory in bytes uint32 DirEntry::fileSize(){ //According to Microsoft FAT specification //The DIR_FileSize field holds the 32-bit quantity containing size in bytes of file/directory described by this entry //DIR_FileSize field has an offset of 28 and size of 4 bytes return *(uint32*)(&_data[28]); }
//Return the order of the entry in the set of LFN entries //It should be noted that only LFN entries hold this field //@return {uint32} : The order of the entry uint32 DirEntry::lfnIndex(){ //According to Microsoft FAT specification: //The order of the entry is defined in LDIR_Ord field //LDIR_Ord field has an offset of 0 and size of 1 byte // //It should also be noted that the field can be masked with 0x40 if it's the last entry in the set // //Therefore, bit 6 should be masked out during returing // //A pretty safe way is to return only the low 6 bits of this field //since the long filename would not exceed the 255 characters limit, //which equals to 255/13 = 20 = 0x14 entries, of which bit 5 is not even used for maximum length filename return _data[0] & 0x3F; }
//Extract every first bit out of two bits of the filename //transforming the filename into ASCII format and copy the transformed filename to dst //It should be noted that this function BEHAVE DIFFERENTLY in SFN and LFN entries //- in LFN entries: the filename is transformed into ASCII and copied to param dst //- in SFN entries: the short filename is copied to param dst //@param {byte*} dst : Destination memory where the filename will be copied to voidDirEntry::parseASCIIFileName(byte* dst){ //According to Microsoft FAT specification: if(isLFNEntry()) { //The filename in LFN entry is stored in three parts //LDIR_Name1 has an offset of 1 and size of 10 bytes //LDIR_Name2 has an offset of 14 and size of 12 bytes //LDIR_Name3 has an offset of 28 and size of 4 bytes //The file name is stored in UNICODE which is 16-bit per character // //Since only English words is used in the implementation //it's okay to extract every frist bit out of two to transform UNICODE into ASCII for(int i = 0; i < 5; i++) { dst[i] = _data[1 + 2 * i]; } for(int i = 0; i < 6; i++) { dst[5 + i] = _data[14 + 2 * i]; } for(int i = 0; i < 2; i++) { dst[11 + i] = _data[28 + 2 * i]; } } else { //The filename in SFN entry is sotred in DIR_Name field //which as an offset of 0 and size of 11 bytes for(int i = 0; i < 11; i++) { dst[i] = _data[i]; } } }
//Calculate/Return the checksum of the entry //It should be noted that this function BEHAVE DIFFERENTLY in SFN and LFN entries //@return {uint32} : Calculate checksum out of filename in SFN entries //@return {uint32} : Return checksum in LFN entries uint32 DirEntry::checkSum(){ if(isSFNEntry()) { //ChkSum() //Returns an unsigned byte checksum computed on an unsigned byte //array. The array must be 11 bytes long and is assumed to contain //a name stored in the format of a MS-DOS directory entry
//The following method is copied from Microsoft FAT specification //page 32, chapter 7.2 Checksum generation byte* pName = &_data[0]; uint16 nameLen; uint8 sum; sum = 0; for(nameLen = 11; nameLen != 0; nameLen--) { //NOTE: The operation is an unsigned char rotate right sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + *pName++; } return sum; } else { //According to Microsoft FAT specification: //The checksum in LFN entries is stored in LDIR_Chksum field //which has an offset of 13 and size of 1 byte return _data[13]; } }
//Assume there is a MBR typed variable mbr //假设已经有一个MBR类型的对象mbr Partition p = mbr.partition_1; //Check the status of the partition //检查分区是否是活动的 if(p.isActive()){ //Do something if the partition is active //如果分区是活动的,则会执行的代码 } //Get the LBA of first sector //获取分区第一个扇区的LBA扇区号 lba = p.firstSectorLBA();