- ;By Marcus Xing
- ;boot/include/lib_in_real_mode.inc
- ;在boot/loader.asm中在实模式下调用的函数
- ;--------------------------------------------------------------------Read_Sector
- Read_Sector:
- ;C函数原型(实模式下调用,短调用):
- ;void Read_Sector(byte16 first_sector_index,byte16 read_sector_number);
- ;注意:
- ;调用前es:bx必须指向缓冲区,ds指向数据区
- ;逻辑扇区号转化为系统调用所需参数的公式如下:
- ;相对扇区号/每磁道扇区号(18)的商Q,余数R
- ;其中:柱面号=Q>>1,磁头号=Q&1,相对起始扇区号=R+1
- ;对应的系统调用API如下:
- ;功能号ah=02
- ;hal=要读的扇区数
- ;ch=柱面(磁道)号
- ;cl=起始扇区号
- ;dh=磁头号,dl=驱动器号(0表示A盘)
- ;es:bx缓冲区地址
- push bp
- mov bp,sp
- push ax
- push bx
- push cx
- push dx
- push bx ;暂存缓冲区偏移
- mov ax,[bp + 6] ;取得要读取的扇区数
- push ax ;暂时保存之
- mov ax,[bp + 4] ;取得要读的逻辑扇区号
- mov bl,18
- div bl ;除以每柱面扇区数
- mov ch,al
- shr ch,1 ;ch<-柱面号
- mov dh,al
- and dh,1 ;dh<-磁头号
- mov cl,ah
- inc cl ;cl<-相对扇区号
- mov dl,0 ;读A盘
- pop ax ;al<-要读的扇区数
- pop bx ;恢复缓冲区偏移
- .Go_On_Reading:
- mov ah,2 ;ah<-功能号
- int 13h
- jc .Go_On_Reading ;如果cf=1,继续读
- pop dx
- pop cx
- pop bx
- pop ax
- pop bp
- ret
- ;------------------------------------------------------------------Get_FAT_Entry
- Get_FAT_Entry:
- ;C函数原型(实模式下调用,短调用):
- ;u16 Get_FAT_Entry(u16 Sector_No_In_Data_Area);
- ;功能:
- ;入口参数为数据区的相对扇区号,返回值为相应的FAT的值,以表示还有没有下一个扇区
- ;ds指向数据区,在此函数中,es:bx=9000h-100h:0用来作为读FAT的缓冲区
- push bp
- mov bp,sp
- push bx
- push dx
- push es
- mov byte [_b_Is_Odd],0 ;作用为局部变量,标记相对FAT的条目索引
- ;es指向9000h-100h
- mov ax,Base_Of_Loader
- sub ax,100h
- mov es,ax
- ;1个FAT条目为12位,条目索引*3/2 = *1.5
- ;ax为相对FAT字节偏移
- mov ax,[bp + 4]
- mov bx,3
- mul bx
- mov bx,2
- div bx
- ;判断余数是否为0,是的话为偶,跳转到
- ;对应标号,否的话把标记变量置1
- cmp dx,0
- je LABEL_EVEN
- mov byte [_b_Is_Odd],1
- LABEL_EVEN:
- ;ax=当前条目在FAT的相对逻辑偏移扇区
- ;dx=当前条目相对当前扇区的字节偏移
- xor dx,dx
- mov bx,512
- div bx
- add ax,1 ;ax自增1,求得相对整个软盘的逻辑扇区偏移
- ;读2个FAT扇区到缓冲区,一次读2个,
- ;因为FAT条目可能跨越2个扇区
- xor bx,bx
- push 2
- push ax
- call Read_Sector
- add sp,4
- mov bx,dx ;es:bx指向要求的条目首字节
- mov ax,[es:bx] ;把首字节存到ax
- cmp byte [_b_Is_Odd],1 ;判断奇偶,奇偶有不同的处理方式
- jne LABEL_EVEN2
- shr ax,4 ;奇数的处理方式
- LABEL_EVEN2: ;偶数的处理方式
- and ax,0fffh ;返回值放到ax中
- LABEL_DONE:
- pop es
- pop dx
- pop bx
- pop bp
- ret
- ;----------------------------------------------------------Disp_Str_In_Real_Mode
- Disp_Str_In_Real_Mode:
- ;C函数原型(实模式下调用,短调用):
- ;void Disp_Str_In_Real_Mode(const char *p_sz_Str);
- ;注意:
- ;在变量_w_Disp_Pos处显示字符串,ds指向数据区,es的值在此函数中指向数据区
- push bp
- mov bp,sp
- push ax
- push bx
- push cx
- push dx
- push di
- push es
- ;此BIOS中断API
- ;功能13H
- ;功能描述:在Teletype模式下显示字符串
- ;入口参数:AH=13H
- ;BH=页码
- ;BL=属性(若AL=00H或01H)
- ;CX=显示字符串长度
- ;(DH、DL)=坐标(行、列)
- ;ES:BP=显示字符串的地址 AL=显示输出方式
- ;0——字符串中只含显示字符,其显示属性在BL中。显示后,光标位置不变
- ;1——字符串中只含显示字符,其显示属性在BL中。显示后,光标位置改变
- ;2——字符串中含显示字符和显示属性。显示后,光标位置不变
- ;3——字符串中含显示字符和显示属性。显示后,光标位置改变
- ;出口参数:无
- mov ax,ds
- mov es,ax
- mov bp,[bp + 4] ;取得要打印的字符串指针
- mov al,[es:bp]
- cmp al,0ah
- jne .3
- mov ax,[_w_Disp_Pos_In_RM]
- mov bl,80
- div bl
- inc al
- mul bl
- mov [_w_Disp_Pos_In_RM],ax
- jmp .4
- .3:
- mov ax,[_w_Disp_Pos_In_RM];得到显示地址
- mov bl,80
- div bl
- mov dh,al ;dh<-行号
- mov dl,ah ;dl<-列号
- xor cx,cx ;字符串长度计数器
- mov di,bp ;做临时指针es:di指向字符串
- .1:
- mov al,byte [es:di]
- cmp al,0 ;遇到0计数结束
- je .2
- inc cx ;计数器自增1
- inc di ;临时指针自增1
- jmp .1
- .2:
- add word [_w_Disp_Pos_In_RM],cx ;显示地址加上字符串长度
- mov bx,0007h ;bh表示第0页,bl表示字符颜色
- mov ax,1301h ;al为输出方式1
- int 10h
- .4:
- pop es
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- pop bp
- ret
- ;---------------------------------------------------------------------Kill_Motor
- Kill_Motor:
- ;C函数原型(实模式下调用,短调用):
- ;void Kill_Motor();
- ;功能:
- ;如名字所示,以免马达灯长亮
- push ax
- push dx
- mov dx,03f2h
- mov al,0
- out dx,al
- pop dx
- pop ax
- ret
boot/include/lib_in_real_mode.inc
本文介绍实模式下的磁盘操作函数,包括扇区读取、获取FAT条目值,以及屏幕显示字符串的功能实现。这些函数用于加载器和启动过程中的基本输入输出操作。

被折叠的 条评论
为什么被折叠?



