boot/include/lib_in_real_mode.inc

;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
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值