赞
踩
随记:
1 在汇编中可以定义函数,函数名使用标签定义, 函数体最后一条指令是 ret, 调用函数 是call function
2 如果代码中定义了函数,那么需要定义栈空间。用于保存关键寄存器的值,栈顶地址通过sp寄存器保存
3 汇编中用 equ 定义常量,如 Const equ 0x7c00 == #define Const 0x7c00 .
4 dx(db,dw,dd) 可以定义变量 他们与 equ的差别在于,equ定义不会占用内存空间,而dx定义占用对应的内存空间
db定义字节类型变量,一个字节数据占1个字节单元,读完一个,偏移量加1
dw定义字类型变量,一个字数据占2个字节单元,读完一个,偏移量加2
dd定义双字类型变量,一个双字数据占4个字节单元,读完一个,偏移量加4
5 and 按位与 运算
6 汇编中的16位除法操作(div)
一 在主引导程序中打印字符串 – 直接调用系统服务
二 主引导程序中读取指定扇区数据 – 直接调用系统服务
不过参数比较麻烦,这涉及到软盘的基本信息:
makefile
.PHONY : all clean rebuild SRC := boot.asm OUT := boot.bin IMG := data.img RM := rm -fr #将主引导程序的二进制程序 烧写到 虚拟软盘的第0个扇区 all : $(OUT) $(IMG) dd if=$(OUT) of=$(IMG) bs=512 count=1 conv=notrunc @echo "Success!" #创建虚拟软盘 $(IMG) : bximage $@ -q -fd -size=1.44 #编译主引导程序代码 成二进制程序 $(OUT) : $(SRC) nasm $^ -o $@ clean : $(RM) $(IMG) $(OUT) rebuild : @$(MAKE) clean @$(MAKE) all
bochsrc 配置
############################################################### # Configuration file for Bochs ############################################################### # how much memory the emulated machine will have megs: 32 # filename of ROM images romimage: file=/usr/local/share/bochs/BIOS-bochs-latest vgaromimage: file=/usr/share/vgabios/vgabios.bin # what disk images will be used floppya: 1_44=data.img, status=inserted # choose the boot disk. boot: a # where do we send log messages? # log: bochsout.txt # disable the mouse mouse: enabled=0 # enable key mapping, using US layout as default. keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/x11-pc-us.map
boot.asm
;主引导程序起始地址 org 0x7c00 ;主引导程序的前三个字节 是跳转指令 ;跳转指令(jmp指令占 一个字节) 跳到start标签(目标地址标签 是短跳转 占一个字节) nop(空指令占一个字节) ;这样写的原因是 下面的定义的 FAT12文件头并不是可执行的代码,所以需要跳过这一段信息 到 start 标签执行 jmp short start nop ;栈空间起始地址 define: BaseOfStack equ 0x7c00 ; FAT12文件系统所需要的头 header: BS_OEMName db "D.T.Soft" BPB_BytsPerSec dw 512 BPB_SecPerClus db 1 BPB_RsvdSecCnt dw 1 BPB_NumFATs db 2 BPB_RootEntCnt dw 224 BPB_TotSec16 dw 2880 BPB_Media db 0xF0 BPB_FATSz16 dw 9 ;每个磁道 扇区数 BPB_SecPerTrk dw 18 BPB_NumHeads dw 2 BPB_HiddSec dd 0 BPB_TotSec32 dd 0 BS_DrvNum db 0 BS_Reserved1 db 0 BS_BootSig db 0x29 BS_VolID dd 0 BS_VolLab db "D.T.OS-0.01" BS_FileSysType db "FAT12 " start: mov ax, cs mov ss, ax mov ds, ax mov es, ax ;指定 sp栈顶指针寄存器 值 mov sp, BaseOfStack ;指定参数 逻辑扇区号:34 mov ax, 34 ;需要连续读取一个扇区 mov cx, 1 ;读取到 buf地址 mov bx, Buf call ReadSector ;调用打印函数前,在寄存器中指定函数参数:字符串地址+长度 ;字符串地址 mov bp, Buf ;字符串长度 mov cx, 29 ;调用打印函数 call Print last: hlt jmp last ;打印函数,用寄存器传参数(目标字符串地址和长度) ; es:bp --> string address 目标字符串地址 ; cx --> string length 长度 Print: ;打印参数 mov ax, 0x1301 mov bx, 0x0007 ;调用中断(调用0x10号中断 打印) int 0x10 ret ; no parameter ;重置软驱 ResetFloppy: ;备份 ax bx 寄存器值,将ax bx 寄存器进栈备份 push ax push dx ;BIOS 中软盘数据读取 中断号0x13,参数(ah=0x00 软驱复位,dl=0 A盘) ;软驱复位 mov ah, 0x00 ;驱动器号 0:A盘 mov dl, [BS_DrvNum] ; BIOS 中软盘数据读取 中断号0x13 int 0x13 ;将ax bx 寄存器出栈(恢复 ax bx 寄存器值),顺序与进栈顺序相反 pop dx pop ax ret ; 读取软驱数据函数 参数: ; ax --> logic sector number 逻辑扇区号 ; cx --> number of sector 需要连续读取多少个扇区 ; es:bx --> target address 读取到的内存位置 ReadSector: ; 进栈备份下面需要使用到的寄存器值,下面使用后再出栈恢复 push bx push cx push dx push ax ;先重置软驱 call ResetFloppy ;bx(读取到的内存位置) cx(需要连续读取多少个扇区) 进栈备份 push bx push cx ;每个磁道扇区数 18 mov bl, [BPB_SecPerTrk] ; 执行除法操作,ax寄存器值/18 = 商位于 AL 寄存器中 余数位于 AH 寄存器中 div bl ;将 ah寄存器值(余数) 放到 cl寄存器 mov cl, ah ;三元素 之 扇区号 add cl, 1 ;将 al寄存器值(商) 放到 ch寄存器 mov ch, al ;三元素 之 柱面号 (sh 寄存器值 右移一位) shr ch, 1 ;三元素 之 磁头号 商按位与1 == 磁头号 放在 dh寄存器 mov dh, al and dh, 1 ;驱动器号 mov dl, [BS_DrvNum] ;将cx 寄存器值 出栈 并弹到 ax 寄存器中 pop ax pop bx ;BIOS 中软盘数据读取 中断号0x13,参数: ; ah=0x02 从磁盘将数据读到ES:BX指向的内存 ; dl= 扇区长度,ch= 柱面号, cl=起始扇区号, dh=磁头号,dl=驱动器号 mov ah, 0x02 ;如果读取失败 则反复读取 直到读取成功 read: int 0x13 ;读完后 查看错误标志位有没有被设置,有的话 跳转到read标签处重读 jc read ;出栈恢复(顺序相反) pop ax pop dx pop cx pop bx ret MsgStr db "Hello, DTOS!" ;字符串长度: 用当前地址 - MsgStr 地址 MsgLen equ ($-MsgStr) Buf: times 510-($-$$) db 0x00 db 0x55, 0xaa
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。