使用nasm的 $ 和$$要注意了

来源:互联网 发布:4万亿计划 知乎 编辑:程序博客网 时间:2024/06/08 15:53
使用nasm的 $ 和$$要注意了,这两个符号是和段有关。
例如,下面的代码使用nasm编译成bin格式的文件后,不能在末尾加上启动扇区标识0xaa55,原因就在于“[section .data]”,这个section,导致了$ 和$$不能按照我的预期工作,仔细查看nasm的手册才明白了,所以记下来。


%define DEBUG_POINT xchg bx, bx
org  07c00h; Boot 状态, Bios 将把 Boot Sector 加载到 0:7C00 处并开始执行
jmp LABEL_BEGIN
;one_byte db 0 ; FAT 引导扇区的格式

BS_OEMName db'aiht\0\0\0\0' ;OEM string,必须8个字节
BPB_BytesPerSec dw512 ;每个扇区的字节数
BPB_SecPerClus db1 ;每个簇含有的扇区数
BPB_RsvdSecCnt dw1 ;boot占用的扇区数
BPB_NumFATs db2 ;FAT表的个数
BPB_RootEntCnt dw0xE0 ;根目录文件最大值
BPB_TotalSec16 dw0xB40 ;扇区总数
BPB_Media db0xF0 ;介质描述符
BPB_NumPerFAT dw9 ;每个FAT的扇区数
BPB_SecPerTrk dw 0x12 ;每磁道扇区数
BPB_NumHeads dw0x2 ;磁头数
BPB_HideSec dd0 ;隐藏扇区数
BPB_TotalSec32 dd0 ;如果BPB_TotalSec16的值为0,则由此字段记录总扇区数
BS_DrvNum db0 ;中断13的驱动器号
BS_Reserved1 db0 ;未使用
BS_BootSig db0x29 ;扩展引导标记
BS_VolID dd0 ;卷序列号
BS_VolLab db'OrangeS\0\0\0\0';卷标
BS_FileSysType db'FAT12\n\n\n' ;文件系统类型

[section .data]

;end of [section .data]

;define macro for const via
BegSecNumRootDir equ0;根目录起始扇区号
EntSizeRootDir equ0x16;根目录条目大小
;1.44M软盘参数
TrkNumPerHeader equ80;每个盘面的柱面(磁道)数
;
;end define

LABEL_BEGIN:
;初始化各段寄存器
mov ax, cs
mov ds, ax
mov ss, ax
mov es, ax
mov sp, 0x7C00

DEBUG_POINT
;复位软驱
xor ah, ah
mov dl, [BS_DrvNum]
int 13
;初始化根目录扇区号
mov ax, [BPB_NumPerFAT]
mov bl, [BPB_NumFATs]
mul bl
test dx, dx ;dx是乘积的高16位
jnz LABEL_END
inc ax

;查找根目录下的有无loader.bin
;1.求出柱面编号
mov eax, [BegSecNumRootDir]
mov bl, [BPB_SecPerTrk]
div bl ;
push ax ;保存商
;2、两个盘面,柱面是跨盘面的,因此需要除以盘面数(2),用shr优化,不用div
shr al, 1 ;商除2
mov ch, al ;柱面号存入ch
inc ah
mov cl, ah ;起始扇区号存入cl
mov bl, [BPB_NumHeads]
pop ax
xor ah, ah
div bl
mov dh, ah ;磁头号存入dh
mov dl, [BS_DrvNum] ;驱动器号存入dl

mov ah, 0x2;读操作
mov al, 1 ;读取的扇区数

sub sp, 512;堆栈上分配512byte作为缓冲区
mov bx, sp;es:bx指向缓冲区
int 13;
LABEL_END:
jmp $;
;读取loader.bin
;控制权移交给loader
;----------------------------------------------------------------------------------------------
times 510-($-$$)db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55; 结束标志