/* 这份代码将编译后将放到GRLDR文件的0x400开始的地方(即第三个扇区)* 这个扇区的内容将被塞到分区引导扇区* 其中0x00-0x59见文章下方表1。* 0x5a - 0x1fc放引导代码。* 最后两个字节固定是0xAA55。** 这份代码将加载到0000:7C00执行。* 作用是在一个fat32分区中寻找根目录下的GRLDR文件。* 找到后将整个文件载入到2000:0000(0x20000,即128K)开始的位置,然后执行它。*/. = _start1 + 0x400#define ALTERNATIVE_KERNEL/** 以下基于FreeDOS,Tinybit在2004年2月对其进行了重大修改** 将LBA和CHS引导扇区合并为一个FAT32引导扇区!** GRLDR FAT32单阶段引导过程的内存布局:**    ...*    |-------| 1FE0:7E00*    |BOOTSEC| (GRUB不使用此重定位区域)*    |RELOC.    | (被加载的内核覆盖)*    |-------| 1FE0:7C00*    ...*    |-------|*    |KERNEL    | (覆盖bootsec重定位。)*    |LOADED    | (在内核加载之前保存1个扇区目录缓冲区)*    |-------| 2000:0000*    ...*    |-------| 0000:7E00*    |BOOTSEC| GRUB始终在该sector内运行,*    |ORIGIN | 没有重定位.*    |-------| 0000:7C00*    ...*    |-------| 0060:0200*    |  FAT  | (仅1个扇区被缓冲)*    |-------| 0060:0000*    ...**//*
; 这是启用了LBA的FreeDOS FAT32引导扇区(单个扇区!)。
; You can use and copy source code and binaries under the terms of the
; GNU Public License (GPL), version 2 or newer. See www.gnu.org for more.; 基于FreeDOS内核黑客的早期工作, 由Eric Auer和Jon Gentle在2003年7月进行了重大修改。
;
; 特点:使用LBA并根据BPB / EBPB数据计算所有变量,从而使分区移动/调整大小/图像恢复更加容易。
; FreeDOS可以在> 8 GB边界的FAT32分区中从此启动扇区开始启动。 引导不需要磁盘几何知识。
;
; Windows使用2-3个扇区进行引导(扇区阶段,统计扇区,文件系统阶段)。
; 对于FreeDOS仅使用1个扇区,可以更轻松地在同一文件系统上做FreeDOS和Windows的多系统引导。
;
; 要求:LBA BIOS和386或更好的CPU。 如果要在真正旧的PC上使用FAT32,请使用较旧的仅CHS引导扇区
;(问题:如果您使用仅CHS的FAT32引导扇区在再次应用SYS之前无法从> 8 GB边界引导,无法移动/调整大小... ...)。
;
; FAT12 / FAT16提示:除非您必须从> 8 GB启动否则使用较旧的仅CHS引导扇区。 LBA和CHS FAT12 / FAT16引导扇区需要在移动/调整大小/ ...之后再次应用SYS。
; a variant of that boot sector without CHS support but with better move / resize / ...
; support would be good for use on LBA harddisks.
; FreeDOS FAT32单阶段启动过程的内存布局:
;    ...
;    |-------| 1FE0:7E00
;    |BOOTSEC|
;    |RELOC.    |
;    |-------| 1FE0:7C00
;    ...
;    |-------| 2000:0200
;    |  FAT  | (only 1 sector buffered)
;    |-------| 2000:0000
;    ...
;    |-------| 0000:7E00
;    |BOOTSEC| overwritten by the kernel, so the
;    |ORIGIN | bootsector relocates itself up...
;    |-------| 0000:7C00
;    ...
;    |-------|
;    |KERNEL    | maximum size 134k (overwrites bootsec origin)
;    |LOADED    | (holds 1 sector directory buffer before kernel load)
;    |-------| 0060:0000
;    ...
*/#define BOOTGRUB    /* undef this if compiled for loading FreeDOS */
//#undef BOOTGRUB#ifdef    BOOTGRUB
#define LOADSEG        0x2000
#define FATSEG        0x0060
#else
#define LOADSEG        0x0060
#define FATSEG        0x2000
#endifEntry_32:jmp    1f. = Entry_32 + 0x02/* 默认模式是CHS。 这是为了最大程度地兼容小型磁盘(例如软盘)。* 对于CHS模式,有效值为0x90,对于LBA模式,有效值为0x0e。* 如果BIOS int13支持LBA,则可以将该字节安全地设置为0x0e。* 使用CHS模式时,某些USB BIOS可能存在错误,因此格式化程序应将此字节* 设置为0x0e。 看来(通常)所有USB BIOS具有LBA支持。* 如果格式化程序不知道BIOS是否支持LBA,则它可以通过以下方式运行:* 如果(partition_start + total_sectors_in_partition)超过了CHS寻址* 能力(尤其是当它大于1024 * 256 * 63时),则调用者应将此字节设置为* 0x0e,否则设置为0x90。*/.byte    0x90           /* 用于CHS,另一个可能的值为代表LBA的0x0e */. = Entry_32 + 0x03#ifdef    BOOTGRUB.ascii    "GRLDR   "    /* (格式化磁盘的操作系统的)OEM名字 */
#endif. = Entry_32 + 0x0b.word    0x200          /* 每个扇区的字节数。 必须为512 */. = Entry_32 + 0x0d/* 每簇扇区数。 有效值为1、2、4、8、16、32、64和128。* 但是不应该出现大于32K的簇大小。*/.byte    1              /* 每簇扇区数 */. = Entry_32 + 0x0e/* * 保留扇区数(第一个FAT之前的扇区数,包括引导扇区),通常为1。*/.word    1              /* 保留扇区数 */. = Entry_32 + 0x10/* FAT数量(几乎总是2个). */.byte    2              /* FAT数量 */. = Entry_32 + 0x11/* 根目录的目录(root directory entries)最大数个数必须为0。 */.word    0              /* Max dir entries for FAT12/FAT16 */. = Entry_32 + 0x13/* (扇区总数,仅适用于小磁盘)必须为0。 */.word    0              /* total sectors for FAT12/FAT16 */. = Entry_32 + 0x15/* 媒体描述符字节,现在已经无意义。 */.byte    0xf8           /* media descriptor */. = Entry_32 + 0x16/* (每个FAT的扇区数)必须为0。 */.word    0              /* sectors per FAT for FAT12/FAT16 */. = Entry_32 + 0x18.word    18             /* 每磁道扇区数 */. = Entry_32 + 0x1a.word    2              /* 磁头数 */. = Entry_32 + 0x1c/** 隐藏扇区的数量(引导扇区之前的扇区),也称为分区的起始扇区。对于软盘应为0。*/.long    0              /* hidden sectors */. = Entry_32 + 0x20/* 文件系统中的扇区总数。 */.long    0              /* total sectors for FAT32 */. = Entry_32 + 0x24/* 每个FAT的FAT32扇区数 */.long    0. = Entry_32 + 0x28/* If bit 7 is clear then all FATs are updated, * 否则,第0-3位将给出当前的活动FAT,所有其他位保留未用。 grldr引导代码不使用该word。*/.word    0. = Entry_32 + 0x2a/* * 高字节是主要修订版号,低字节是次要修订版号,当前两者均为0。* grldr引导代码不使用此word。*/.word    0. = Entry_32 + 0x2c/* 根目录开始簇 */.long    0. = Entry_32 + 0x30/* * 文件系统信息扇区号。 grldr引导代码不使用该word。*/.word    0. = Entry_32 + 0x32/* * 如果非零则是保存引导记录副本的扇区,通常为6。* grldr引导代码不使用此word。*/.word    6. = Entry_32 + 0x34/* 保留的12个字节,设置为0. */.long    0.long    0.long    0. = Entry_32 + 0x40/* 引导设备的驱动器号。程序将DL写入该字节。* 调用者应在DL中设置驱动器号。我们假设所有BIOS在DL中传递正确的* 驱动器号。也就是说不支持错误的BIOS!*/.byte    0. = Entry_32 + 0x41/* * 引导驱动器中此文件系统的分区号。引导代码会将分区号写入该字节。 请参阅下面的Entry + 0x5d。*/.byte    0. = Entry_32 + 0x42/* 签名(必须为28h或29h才能被NT识别)。 */.byte    0x29              /* FAT12/FAT16的扩展启动签名 */. = Entry_32 + 0x43.long    0x0AC4AF63        /* 卷序列号 */. = Entry_32 + 0x47.ascii    "NO NAME    "    /* 卷标签,11个字节。 */. = Entry_32 + 0x52.ascii    "FAT32   "       /* 文件系统ID,8个字节。 *//*
;         bp初始化为7c00h
; %define bsOemName        bp+0x03    ; OEM label (8)
; %define bsBytesPerSec    bp+0x0b ; bytes/sector (dw)
; %define bsSecPerClust    bp+0x0d    ; sectors/allocation unit (db)
; %define bsResSectors     bp+0x0e    ; # reserved sectors (dw)
; %define bsFATs           bp+0x10    ; # of fats (db)
; %define bsRootDirEnts    bp+0x11    ; # of root dir entries (dw, 0 for FAT32)
;         (Fat32在簇链(Cluster Chain)中有根目录)
; %define bsSectors        bp+0x13    ; # sectors total in image (dw, 0 for FAT32)
;         (if 0 use nSectorHuge even if FAT16)
; %define bsMedia          bp+0x15    ; media descriptor: fd=2side9sec, etc... (db)
; %define sectPerFat       bp+0x16    ; # sectors in a fat (dw, 0 for FAT32)
;         (FAT32始终使用xsectPerFat)
%define sectPerTrack       bp+0x18    ; # sectors/track
; %define nHeads           bp+0x1a    ; # heads (dw)
%define nHidden            bp+0x1c    ; # hidden sectors (dd)
; %define nSectorHuge      bp+0x20    ; # sectors if > 65536 (dd)
%define xsectPerFat        bp+0x24    ; Sectors/Fat (dd); +0x28 dw flags (for fat mirroring); +0x2a dw filesystem version (usually 0)
%define xrootClst          bp+0x2c    ; Starting cluster of root directory (dd); +0x30 dw -1 or sector number of fs.-info sector; +0x32 dw -1 or sector number of boot sector backup; (+0x34 .. +0x3f reserved)
%define drive              bp+0x40    ; Drive numberbp+0x41    ; partition number for GRLDR%define fat_sector         bp+0x44    ; last accessed FAT sector (dd); (overwriting unused bytes)
%define fat_start          bp+0x48    ; first FAT sector (dd); (overwriting unused bytes)
%define data_start         bp+0x4c    ; first data sector (dd); (overwriting unused bytes)*//* not used: [0x42] = byte 0x29 (ext boot param flag)* [0x43] = dword serial* [0x47] = label (padded with 00, 11 bytes)* [0x52] = "FAT32",32,32,32 (not used by Windows)* ([0x5a]是FreeDOS开始的地方)*/. = Entry_32 + 0x5a
1:clicld#ifdef    BOOTGRUB. = Entry_32 + 0x5c/* 在偏移量0x5d处的字节存储的是要读取的实际分区号(partition number)。* 格式化程序或调用者应将其设置为正确的值。* 对于软盘,它应该为0xff以代表整个驱动器。*/movb    $0xff, %dh    /* 引导分区号(这个0xff在0x5d处,见上面说明) */cmpb    $0xff, %dh    /* 是软盘吗? */jne    1fmovb    $0, %dl       /* 是的,让驱动器号= 0 */
1:
#endifxorw    %ax, %axmovw    $0x7c00, %bp  /* bp = 0x7c00 */#ifndef    BOOTGRUBmovw    %ax, %ds      /* ds = 0 */movw    $0x1fe0, %ax movw    %ax, %es      /* es = ax = 0x1fe0 */movw    %bp, %si      movw    %bp, %di      movw    $0x0100, %cx  /* 从0000:7c00搬运一个扇区到1fe0:7c00 */repz movswljmp    $0x1fe0, $(1f - Entry_32 + 0x7c00)
1:
#endifmovw    %ax, %ss          /* 栈和相对BP也向上移动 */leaw    -0x20(%bp), %spstimovw    %dx, 0x40(%bp)    /* BIOS传递驱动器号到DL中 */pushw    %ssmovb    $0x41, %ahmovw    $0x55AA, %bxint    $0x13              /* 检查In13H扩展(即EBIOS)是否支持(41h),只有存在才可以调用int42 */popw    %dsjc    1f                  /* No EBIOS */cmpw    $0xAA55, %bxjne    1f                 /* No EBIOS */testb    $1, %cljz    1f                  /* No EBIOS *//* EBIOS supported,见下面readDisk_32子函数将修改INT13指令的参数从AX=0201改为AX=4201*/movb    $0x42, (ebios_32 - 1 - Entry_32 + 0x7c00)
1:pushw    %sspopw    %es/* 找出FAT和DATA区域的起始位置* (修改EAX EDX,设置fat_start和data_start变量)*/xorl    %eax, %eaxmovl    %eax, 0x44(%bp)    /* 初始化缓冲区状态。*(bp + 44) = 0 *//* 首先寻找fat_start */movw    0x0e(%bp), %ax     /* 取保留扇区数 */addl    0x1c(%bp), %eax    /* 加上隐藏扇区数 */movl    %eax, 0x48(%bp)    /* 等于第一个FAT扇区的起始位置 */movl    %eax, 0x4c(%bp)    /* 同时作为第一个数据扇区的位置的初始值(下面还要加上另一个数) *//* 下一步寻找data_start */movl    0x10(%bp), %eax    /* fat数(number of fats), 不需要使用movzbl指令:对于fat32,0x11(%bp)所在的2个word是0 */mull    0x24(%bp)          /* 乘以每个fat的扇区数(这里EDX=0,所以下面只取EAX) */addl    %eax, 0x4c(%bp)    /* 加上第一个FAT扇区的起始位置,则得到第一个DATA扇区的起始位置 *//* * 在根目录中搜索文件。* 返回值:EAX=文件的第一个簇*/movl    0x2c(%bp), %eax    /* 取根目录的簇 */1:pushl    %eax              /* 根目录所在簇入栈 */call    cluster_to_lba_32  /* 调用函数,将将簇号转换为绝对扇区号。返回值中EDX是每个簇的扇区数,EAX是扇区号 */movw    $(msg_BootError_32 - Entry_32 + 0x7c00), %si  /* msg_BootError_32 = "NO GRLDR" */jc    boot_error_32        /* 遇到了EOC(EndOfChain) */2:lesw    (loadseg_off_32 - Entry_32)(%bp), %bx    /* 载入到loadseg:0,高位字放ES低位放指令中指定的BX */call    readDisk_32        /* 从磁盘中读一个扇区到ES:BX */xorw    %di, %di/* 在目录中搜索内核文件(或者GRLDR)名,并找到文件所在的起始簇.* 关于目录项(Directory Entry)见下方的图1*/
3:movw    $11, %cxmovw    $(filename_32 - Entry_32 + 0x7c00), %si /* ESI = "GRLDR      " */repz cmpsbjz    1f                   /* 找到了,注意DI现在等于dirent+11 */addw    $0x20, %di         /* 以32 Bytes划分为一个单位,每个单位称为一个目录项(Directory Entry)*/andw    $-0x20, %di        /* 0xffe0 */cmp    0x0b(%bp), %di      /* 每个扇区字节数 */jnz    3b                  /* 匹配下一个目录条目 */decw    %dx                /* 最初DX存放每个簇的扇区数,遍历完一个扇区后递减 */jnz    2b                  /* 遍历所有簇内的扇区 */popl    %eax               /* 根目录所在簇出栈 */call    next_cluster_32jmp    1b                  /* 读下个簇 */#ifndef ALTERNATIVE_KERNEL
loadseg_off_32:.word    0.word    LOADSEG
#endif1:/* 找到了目录项 */pushw    %es:(0x14-11)(%di)  /* 文件起始簇号的高16位 */pushw    %es:(0x1a-11)(%di)  /* 文件起始簇号的低16位 */popl    %eax                 /* 转为32位数 */xorw    %bx, %bx             /* 读取内核(这里是GRLDR)文件到ES:BX=LOADSEG:0 *//* read kernel */2:pushl    %eaxcall    cluster_to_lba_32    /* 簇号转扇区号。调用后EDX是每个簇的扇区数,EAX是扇区号 */jnc    1f/* 遇到了EOC,循环结束(这里是上面2:和下面1:的循环出口)*/
#ifdef    BOOTGRUBmovw    0x40(%bp), %dx       /* boot_drive和boot_partition */
#elsemovb    0x40(%bp), %bl       /* FreeDOS 内核使用BL而不是DL存放引导驱动器号 */
#endifpushw    %dx                 /* for loading grub.exe */ljmp    *(loadseg_off_32 - Entry_32)(%bp)    /* 跳到我们加载的地方执行(即执行GRLDR或者MSDOS内核) */1:call    readDisk_32          /* 读一个扇区 */decw    %dx                  /* 开始的时候DX存放的是每簇扇区数 */jnz    1b                    /* 遍历读取簇中的所有扇区 */popl    %eaxcall    next_cluster_32      /* 找到下一个簇 */jmp    2b/* 给定一个簇编号,找到FAT链中下一个簇的编号。 * 需要fat_start。* input:    EAX - 簇编号*        EDX = 0* output:    EAX - FAT链中下一个簇的编号。 *        EDX = undefined*/next_cluster_32:pushw    %es/* pushw    %di */pushw    %bx          /* 未使用EBX的高WORD */#if 1/* xorl    %edx, %edx */shll    $2, %eax      /* 32bit FAT */movzwl    0x0b(%bp), %ebx    /* 一个扇区中的字节数(512) */divl    %ebx          /* 余数在EDX *//* movw    %dx, %di */
#else    shll    $2, %eax      /* 32bit FAT */;xchgw    %ax, %di    /* movw    %ax, %di */movw    %ax, %di;shlw    $2, %di      /* 32bit FAT */pushw    %cxmovw    0x0b(%bp), %bx    /* bytes per sector */bsfw    %bx, %cx;decw    %cx;decw    %cxdecw    %bxandw    %bx, %di      /* mask to sector size */shrl    %cl, %eaxpopw    %cx
#endif    addl    0x48(%bp), %eax    /* add the first FAT sector number.  */ /* EAX=absolute sector number */movw    $FATSEG, %bxmovw    %bx, %esxorw    %bx, %bx/* is it the last accessed and already buffered FAT sector? */cmpl    0x44(%bp), %eaxjz    1fmovl    %eax, 0x44(%bp)    /* mark sector EAX as buffered */call    readDisk_32        /* read sector EAX to buffer */
1:
#if 1//.byte    0x67, 0x26, 0x80, 0x62, 0x03, 0x0faddr32 andb    $0x0f, %es:3(%edx)    /* mask out top 4 bits *///.byte    0x67, 0x66, 0x26, 0x8b, 0x02addr32 movl    %es:(%edx), %eax      /* read next cluster number */
#elseandb    $0x0f, %es:3(%di)  /* mask out top 4 bits */movl    %es:(%di), %eax    /* read next cluster number */
#endifpopw    %bx/* popw    %di */popw    %esret/* 将簇号转换为绝对扇区号* ... 如果EndOfChain则返回进位以表示错误! 需要data_start。* 输入:    EAX - 目标簇号* 输出:    EAX - 绝对扇区号*          EDX - [bsSectPerClust] (byte)*          carry clear*          (如果进位设置了而EAX/EDX不变则EndOfChain)*/cluster_to_lba_32:cmpl    $0x0ffffff8, %eax    /* check End Of Chain */cmcjb    1f                     /* 如果EOC,进位存储 *//* sector = (cluster-2) * clustersize + data_start */decl    %eaxdecl    %eaxmovzbl    0x0d(%bp), %edx    /* 每个簇的扇区数 */pushw    %dx                 /* 只有DX会变化 */mull    %edx                 /* 扇区数 * (簇号-2)(相乘的数字都很小所以EDX总是为0) */popw    %dxaddl    0x4c(%bp), %eax      /* + data_start *//* here, carry is cleared (unless parameters are wrong) */
1:ret/* 从磁盘中读一个扇区,使用LBA或CHS。* input: EAX - 32位DOS扇区号*        ES:BX - 目标缓冲区(将用于填充一个扇区的数据)* output:  ES:BX指向最后读取的字节之后的一个字节。*          EAX - 下一扇区号*/readDisk_32:/* 构建int 13h/42h或者int 13h/02h的参数*/pushalxorl    %edx, %edx   /* EDX:EAX = LBA */pushl    %edx        /* 保存绝对扇区号的高32位到栈 */pushl    %eax        /* 保存绝对扇区号的低32位到栈 */pushw    %es         /* 保存缓冲区的节寄存器 */pushw    %bx         /* 保存缓冲区的偏移 */pushw    $1          /* 读1扇区 */pushw    $16         /* 参数块的大小 */xorl    %ecx, %ecxpushl    0x18(%bp)   /* 高WORD每磁道扇区数,低WORD磁头数 */popw    %cx          /* ECX = 每磁道扇区数 */divl    %ecx         /* 绝对扇区数除以每磁道扇区数。余数(在磁道中的相对扇区号)在EDX中,商(磁道ID)在EAX中 */incw    %dx          /* 在磁道中的相对扇区号 */popw    %cx          /* ECX = 磁头数 (注意PUSHL一次,POPW两次完成赋值)*/pushw    %dx         /* 入栈在磁道中的相对扇区号 */xorw    %dx, %dx     /* EDX:EAX = 磁道数 * 总磁头数 + head */divl    %ecx         /* 磁道ID在EAX中,这里除以磁头数得到该磁道所在的磁头号(商在EAX),以及在所在磁头中的相对磁道号(余数在EDX) */xchgb    %dl, %dh    popw    %cx          /* 出栈相对扇区号 */xchgb    %al, %ch    /* lo 8bit cylinder should be in CH, AL = 0 */shlb    $6, %ah      /* hi 2bit cylinder ... */orb    %ah, %cl      /* ... should be in CL */movw    $0x201, %ax  /* read 1 sector */
ebios_32: /* “ ebios_32-1”指向0x02,可以将其更改为0x42,见上面修改ebios_32-1值的代码 */movw    %sp, %si     /* DS:SI指向硬盘寻址参数块(disk address packet) */movb    0x40(%bp), %dl    /* 硬盘驱动器号 */pushw    %espushw    %dsint    $0x13         /* 调用int13h/42h或者int 13h/02h读磁盘 */popw    %dspopw    %espopaw                /* 从堆栈中删除参数块 */popaljc    disk_error_32  /* disk read error, jc 1f if caller handles */incl     %eax        /* next sector */addw    0x0b(%bp), %bx    /* bytes per sector */jnc    1f            /* 64K bound check */pushw    %dxmovw    %es, %dxaddb    $0x10, %dh   /* add 1000h to ES *//* here, carry is cleared */movw    %dx, %espopw    %dx
1:/* carry stored on disk read error */ret//    . = . - (. - readDisk_32)/91msg_DiskReadError_32:.ascii    "disk error\0"msg_BootError_32:.ascii    "No "filename_32:#ifdef    BOOTGRUB.ascii    "GRLDR      \0"
#else.ascii    "KERNEL  SYS\0"
#endif#ifdef ALTERNATIVE_KERNEL
filename_end_32:. = Entry_32 + 0x1e8loadseg_off_32:.word    0.word    LOADSEG. = Entry_32 + 0x1ecboot_image_ofs_32:.word (filename_32 - Entry_32)+(filename_end_32 - filename_32 - 1)*2048
#endif. = Entry_32 + 0x1eedisk_error_32:movw    $(msg_DiskReadError_32 - Entry_32 + 0x7c00), %siboot_error_32:/* prints string DS:SI (modifies AX BX SI) *///print_32:
1:lodsb    (%si), %al    /* get token *///xorw    %bx, %bx     /* video page 0 */movb    $0x0e, %ah     /* print it */int    $0x10           /* via TTY mode */cmpb    $0, %al        /* end of string? */jne    1b              /* until done *//* The caller will change this to*    ljmp    $0x9400, $(try_next_partition - _start1)*/1:    jmp    1b. = Entry_32 + 0x1fc.word    0, 0xAA55     /* Win9x uses all 4 bytes as magic value here */. = Entry_32 + 0x200
表1 分区引导扇区头部内容
1 0x00~0x02:3字节 “EB5890”,跳转指令。“EB 58”,就是代表汇编语言中的“JMP 58”。 一条空的指令NOP(90H)
2 0x03~0x0A:8字节 文件系统标志和版本号,这里为GRLDR
3 0x0B~0x0C:2字节 每扇区字节数,512(0X02 00)。
4 0x0D~0x0D:1字节 每簇扇区数,8(0x08),这个值不能为0,而且必须是2的整数次方,比如1、2、4、8、16、32、64、128。规定每簇最大的容量不超过1024* 32,1024* 32/512=64
5 0x0E~0x0F:2字节 保留扇区数,38(0x00 26),那么就知道FAT1起始位置在38扇区。
6 0x10~0x10:1字节 FAT表个数为2,另外一个是备份的。
7 0x11~0x12:2字节 FAT32必须等于0,FAT12/FAT16为根目录中目录的个数;
8 0x13~0x14:2字节 FAT32必须等于0,FAT12/FAT16为扇区总数。
9 0x15~0x15:1字节 哪种存储介质,现在已经无意义。0xF8标准值即可移动存储介质。
10 0x16~0x17:2字节 FAT32必须为0,FAT12/FAT16为一个FAT表所占的扇区数。
11 0x18~0x19:2字节 每磁道扇区数,只对于“CHS”(由磁头和柱面每 分割为若干磁道)的存储介质有效,18。
12 0x1A~0x1B:2字节 磁头数,只对CHS介质才有效,2
13 0x1C~0x1F:4字节 EBR分区之前所隐藏的扇区数,0(0x00 00 00 00)
14 0x20~0x23:4字节 此文件系统分区的总扇区数
15 0x24~0x27:4字节 每个FAT表占用扇区数
16 0x28~0x29:2字节 标记,此域FAT32 特有。 grldr引导代码不使用该word。
17 0x2A~0x2B:2字节 FAT32版本号0.0,FAT32特有。grldr引导代码不使用该word。
18 0x2C~0x2F:4字节 根目录所在第一个簇的簇号,2。(虽然在FAT32文件系统 下,根目录可以存放在数据区的任何位置,但是通常情况下还是起始于2号簇)。
19 0x30~0x31:2字节 FSINFO(文件系统信息扇区)扇区号是1,该扇区为操作系统提供关于空簇总数及下一可用簇的信息。 grldr引导代码不使用该word。
20 0x32~0x33:2字节 备份引导扇区的位置,通常为6。grldr引导代码不使用此word。
21 0x34~0x3F:12字节 保留的12个字节,设置为0。用于以后FAT 扩展使用。
22 0x40~0x40:1字节

与FAT12/16 的定义相同,只不过两者位于启动扇区不同的位置而已。

对于Grub4dos作用是保存引导设备的驱动器号。程序将DL写入该字节。调用者应在DL中设置驱动器号。我们假设所有BIOS在DL中传递正确的驱动器号。也就是说不支持错误的BIOS!

23 0x41~0x41:1字节

与FAT12/16 的定义相同,只不过两者位于启动扇区不同的位置而已 。

对于Grub4dos用保存引导驱动器中此文件系统的分区号。引导代码会将分区号写入该字节。 请参阅下面的Entry + 0x5d。

24 0x42~0x42:1字节 扩展引导标志签名(必须为28h或29h才能被NT识别)0x29。与FAT12/16 的定义相同,只不过两者位于启动扇区不同的位置而已
25 0x43~0x46:4字节 卷序列号。通常为一个随机值。对于GRUB4DOS是0x0AC4AF63
26 0x47~0x51:11字节 卷标(ASCII码),如果建立文件系统的时候指定了卷标,会保存在此。对于GRUB4DOS默认是"NO NAME    "
27 0x52~0x59:8字节 文件系统格式的ASCII码”FAT32“

图1 目录项的内容。

GRUB4DOS(十二)适用于FAT32的分区引导扇区启动代码相关推荐

  1. DBR(分区引导扇区)

    DBR 主要由下列几个部分组成: 1.跳转指令,占用3个字节的跳转指令将跳转至引导代码 2.厂商标识和DOS版本号,该部分总共占用8个字节. 3. BPB(BIOS Parameter BlockBI ...

  2. App设计灵感之十二组精美的插画引导页设计案例

    引导页是软件打开时首先呈现在用户眼前的第一个页面,如何才能在引导页这里快速吸引用户的注意力?这十二组插画引导页也许会带给你灵感. ① Food Delivery - Mobile App by Ana ...

  3. 硬盘主引导扇区汇编代码

    GitHub地址:https://github.com/yifengyou/X86-assembly-language-from-real-mode-to-protection-mode/blob/m ...

  4. php文件上传漏洞防御,第十二课 php文件上传漏洞和代码防御

    挖掘上传漏洞 常见上传函数 $_FILES  move_uploaded_file等函数 搜索关键字 $_FILES  move_uploaded_file 如何防止上传漏洞 自定义文件扩展名和路径 ...

  5. 十二、程序返回、数据类型表示、代码注释

    1. 程序返回 功能:程序返回,结果执行 语法: mov ax,4c00H int 21H 2. 数据类型表示 十进制数(D) 二进制数(B) 十六进制数(H) 字符:'a'   //对应16进制61 ...

  6. 第十二章 软件壳(四)(代码抽取型壳)

    文章目录 代码抽取型壳 内存重组脱壳法 Hook 脱壳法 系统定制脱壳法 脱壳工具 代码抽取型壳 即第二代壳 主要特点 即使 DEX 已加载到内存,仍处于加密状态(所有 DEX 方法都在运行时解密) ...

  7. 【Linux开发】linux设备驱动归纳总结(十二):简单的数码相框

    linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  8. JavaScript学习(二十二)—动态创建表格

    JavaScript学习(二十二)-动态创建表格 效果如下: 代码如下: <!DOCTYPE html> <html lang="en"><head& ...

  9. 编辑引导扇区修复分区引导解决磁盘分区打不开

    关键词:raw格式  数据错误 循环冗余错误  编辑引导扇区  修复分区引导 问题描述: E盘双击打不开,提示是否将其格式化,点取消,提示数据错误(循环冗余错误).计算机-管理-磁盘管理显示格式为ra ...

最新文章

  1. Android学习笔记(1)----播放音乐文件
  2. [训练日志] 7月22-31日
  3. 成功解决sklearn\preprocessing\label.py:151: DeprecationWarning: The truth value of an empty array is amb
  4. Eigen求解数学问题(二)
  5. 漆桂林 | 人工智能的浪潮中,知识图谱何去何从?
  6. 主成分分析法案例_因子分析案例及操作解析
  7. PL/SQL 连接配置
  8. set、vector与list的构造与排序的耗时测试
  9. Lectra力克公司发布新战略 助力客户打造“工业4.0”智造流程
  10. matlab编译桁架有限元计算(附有完整代码)
  11. 关于activity转场动画makeSceneTransitionAnimation没效果的问题的解决办法
  12. 论初唐诗人的历史地位-上官仪、王勃、杨炯、陈子昂、杜审言
  13. python在电脑上怎样下载_怎样在电脑上下载哔哩哔哩的视频?
  14. python爬取微博恶评_详解用python写网络爬虫-爬取新浪微博评论
  15. 计算机中的科学思维能力指哪三种,浅析计算机应用与科学思维能力培养
  16. 解决win10家庭版安装LoadRunner11无法破解问题
  17. lisp语言绘制路灯_LISP语言在AD道路设计方案中各种应用
  18. RN系列文章---RN简介
  19. 计算机一级考试怎么分栏,全国高等学校计算机等级考试(一级)理论汇总_分栏
  20. 小学数学计算机教案模板,小学数学万能教案模板

热门文章

  1. chrome怎么运行Android程序,ARCVM:Chrome OS 中运行 Android 应用程序的新方式
  2. 正则表达式匹配任何空白字符或者非空白字符
  3. Java判断字符串是否为数字(正负、小数)
  4. 监控硬盘与计算机硬盘区别,视频存储烦恼 监控硬盘和普通硬盘区别
  5. SQL*Plus中 Set timing on的时间显示单位
  6. 电子设计常识——阻抗
  7. Linux C/C++ 对于SIGBUS、SIGSEGV等崩溃异常捕获实现
  8. PHP指定日期(时间戳转换)
  9. vue项目如何区分开发、生产和测试环境
  10. eas库存状态调整单不能反审核_金蝶eas凭证无法审核