注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

编程学习

我的网上家园

 
 
 

日志

 
 

13章练习: MBR 内核加载初始化部分  

2013-02-27 15:21:35|  分类: 《x86汇编语言: |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
复习一点知识: 对于向上扩展的段,段界限=段大小-1.
相邻的两个段,用后一个段的起始汇编地址减去前一个段的起始汇编地址=前一个段的段大小.再减1就是前一个段的段界限(向上扩展的段)

;13章练习: MBR 内核加载初始化部分
; 内核存放在硬盘LBA 1扇区
; 内核加载到0X40000
; 用户程序存放在硬盘LBA 50扇区
; diskdata.txt 存放在硬盘LBA 100扇区



core_base_address equ 0x00040000 ;加载内核到内存0X40000  
core_start_sector equ 0x00000001 ;内核起始于硬盘LBA 1扇区

mov ax,cs
mov ss,ax
mov sp,0x7c00

mov ax,[cs:pgdt+0x7c00+0x2]
mov dx,[cs:pgdt+0x7c00+0x4]
mov bx,16
div bx
mov ds,ax
mov bx,dx

mov dword [bx],0
mov dword [bx+0x4],0

;4GB数据段
mov dword [bx+0x8],0x0000ffff
mov dword [bx+0xc],0x00cf9200

;MBR代码段
mov dword [bx+0x10],0x7c0001ff
mov dword [bx+0x14],0x00409800

;栈段
mov dword [bx+0x18],0x7c00fffe
mov dword [bx+0x1c],0x00cf9600
;显示缓冲区
mov dword [bx+0x20],0x80007fff
mov dword [bx+0x24],0x0040920b

mov word [cs:pgdt+0x7c00],39
lgdt [cs:pgdt+0x7c00]

in al,0x92
or al,2
out 0x92,al

cli

mov eax,cr0
or eax,1
mov cr0,eax
jmp 0x10:flush

[bits 32]
flush:
mov eax,0x8
mov ds,eax

mov eax,0x18
mov ss,eax
mov esp,0


mov eax,core_start_sector     ;EAX=内核程序在硬盘上的位置
mov edi,core_base_address     ;EDI=内核程序在内存中的起始地址

mov ebx,edi
mov esi,eax  
call read_harddisk_0
mov eax,[edi]
xor edx,edx
mov ecx,512
div ecx
or edx,edx
jnz @a
dec eax
@a:
or eax,eax
jz setup
mov ecx,eax
mov eax,esi
read_s:
inc eax
call read_harddisk_0
loop read_s


;说明: 内核头部: 偏移0X4的地方是公用例程段的起始汇编地址 0X8的地方是核心数据段的起始汇编地址
; 0XC的地方是核心代码段的汇编地址 0X10的地方是内核入口点.
setup:
mov esi,[pgdt+0x7c00+0x2] ;ESI指向 GDT起始地址

mov eax,[edi+0x4] ;公用例程段起始汇编地址
mov ebx,[edi+0x8] ;核心数据段的起始汇编地址
sub ebx,eax  
dec ebx  ;EBX=公用例程段的段界限
add eax,edi  ;EAX=公用例程段的基地址
mov ecx,0x00409800;ECX=段属性
call make_gdt_descript ;调用描述符生成子程序

;安装公用例程段描述符
mov [esi+0x28],eax
mov [esi+0x2c],edx

mov eax,[edi+0x8] ;EAX=核心数据段的起始汇编地址
mov ebx,[edi+0xc] ;EBX=核心代码段的起始汇编地址
sub ebx,eax
dec ebx
add eax,edi
mov ecx,0x00409200
call make_gdt_descript

;安装核心数据段描述符
mov [esi+0x30],eax
mov [esi+0x34],edx

mov eax,[edi+0xc]
mov ebx,[edi+0] ;程序总长度 代码段的结束
sub ebx,eax
dec ebx
add eax,edi
mov ecx,0x00409800
call make_gdt_descript

;安装核心代码段描述符
mov [esi+0x38],eax
mov [esi+0x3c],edx

mov word [pgdt+0x7c00],63
lgdt [pgdt+0x7c00]

jmp far [edi+0x10]



;读硬盘子程序 EBX为加载地址,EAX为起始逻辑扇区号
read_harddisk_0:
push eax
push edx
push ecx

push eax
mov dx,0x1f2
mov al,1
out dx,al
pop eax
inc dx
out dx,al
inc dx
shr eax,8
out dx,al
inc dx
shr eax,8
out dx,al
inc dx
shr eax,8
or al,0xe0
out dx,al
inc dx
mov al,0x20
out dx,al

.waits:
in al,dx
and al,0x88
cmp al,0x8
jnz .waits

mov dx,0x1f0
mov ecx,256
.read:
in ax,dx
mov [ebx],ax
add ebx,2
loop .read

pop ecx
pop edx
pop eax
ret


;子程序,生成描述符 ECX=段属性 EAX=段基地址,EBX=段界限 返回EDX:EAX为描述符 EDX高32位,EAX低32位. 
make_gdt_descript:
push ebx
mov edx,eax
shl eax,16
or ax,bx
and edx,0xffff0000
rol edx,8
bswap edx
and ebx,0xf0000
or edx,ebx
or edx,ecx
pop ebx
ret

pgdt dw 0
dd 0x7e00
times 510-($-$$) db 0
db 0x55,0xaa

  评论这张
 
阅读(47)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017