linux011中setup.s文件分析


INITSEG = 0x9000 !原来bootsect所在的段
SYSSEG  = 0x1000 !system所在的段
SETUPSEG= 0x9020 !setup所在的段

.globl begtext,begdata,begbss,endtext,enddata,endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

entry start
start:							
		mov ax,#INITSEG  !将ds设置成0x9000
		mov ds,ax        !
		mov ah,#0x03     !读取cursor pos.BIOS中断0x10读取光标功能号ah=0x03
										 !输入:bh = 页号
										 !返回:ch = 扫描开始线   cl=扫描结束线 
										 !		 dh = 行号(0x00是顶端) dl=列好(0x00是左边)
		xor bh,bh        !
		int 0x10         !
		mov [0],dx       !把光标位置信息存放在0x90000处,控制台初始化时来取
! get memory size(extended mem kb)下面三句取扩展内存的大小值
		mov ah,#0x88     !调用中断0x15,功能号ah=0x88
		int 0x15         !返回:ax=从0x100000(1M)处开始的扩展内存大小
										 !出错则CF置位,ax=出错码
		mov [2],ax       !将扩展内存存储在0x90002处
!get video-card data 下面这段用于取显卡当前显示功能号
		mov ah,#0x0f     !调用BIOS中断0x10,功能号ah=0x0f
										 !返回:ah=字符列数 al=显示模式  bh=当前显示页
		int 0x10         !0x90004(1字)存放当前页,0x90006显示模式,0x90007字符列数
		mov [4],bx       !bh=display page
		mov [6],ax       !al=video mode   ah=window width
!check for VGA/EGA and some config parameters检查显示方式并取参数
										 !掉用BIOS中断0x10
										 !功能号:ah=0x12  bl=0x10
		mov ah,#0x12     !返回:bh=显示状态 (0x01-单色模式,I/O端口=0x3bx)
										 !(0x00-彩色模式 I/O端口=0x3dx)
		mov bl,#0x10     !bl=安装的显示内存
										 !(0x00-64k,0x01-128k,0x02-192k,0x03-256k)
		int 0x10         !cx=显卡特性参数
		mov [8],ax       !???
		mov [10],bx      !0x9000A=安装显卡内存,0x9000B=显示状态(彩色/单色)
		mov [12],cx      !0x9000c=显卡特性参数
!get hd0 data 取第一硬盘的信息。第一个硬盘的参数表的首地址是中断向量0x41的向量值!而
!第二个硬盘的参数表紧接着第一个表的后面,中断向量0x46的向量值也指向这第二个硬盘的参数首地!址。表的长度是16个字节
!下面两段程序分别复制BIOS有关两个硬盘的参数表,0x90080处存放第一个硬盘的表
!0x90090存放第二个硬盘的表
		mov ax,#0x0000   !
		mov ds,ax        !
		lds si,[4*0x41]  !取中断向量0x41的值,也即hd0参数表的地址->ds:si
		mov ax,#INITSEG  !
		mov es,ax        !
		mov di,#0x0080   !传输目的地址:0x9000:0x0080->es:di
		mov cx,#0x10     !共传输0x10字节
		rep              !
		movsb            !
		                 !
		mov ax,#0x0000   !
		mov ds,ax        !
		lds si,[4*0x46]  !
		mov ax,#INITSEG  !
		mov es,ax        !
		mov di,#0x0090   !
		mov cx,#0x10     !
		rep              !
		movsb            !
!检查系统是否存在第二个硬盘,如果不存在则第二个硬盘表清零
!利用BIOS中断调用0x13的取盘类型功能
!功能号ah=0x15
!输入dl=驱动器号(0x8X是硬盘,0x80第一个硬盘,0x81第二个)
!输出:ah=类型码 00--没有这个盘  CF置位,01--软驱,没有change-line支持
!02--软驱(或其他科移动设备),有change-line支持,03--硬盘
		mov ax,#0x01500  !
		mov dl,#0x81     !
		int 0x13         !
		jc no_disk1      !
		cmp ah,#3        !是硬盘吗?
		je is_disk1      !
		                 !
no_disk1:            !
		mov ax,#INITSEG  !不存在则清零
		mov es,ax        !
		mov di,#0x0090   !
		mov cx,#0x10     !
		mov ax,#0x00     !
		rep              !
		stosb            !
		                 !
is_disk1:            !
			
			cli            !关中断
!首先将system模块移到正确位置.bootsect引导程序是将system读取到0x1000开始的位置
!当时假设system最大长度不会超过0x80000(512k),也即末端不会超过内存地址0x90000,所以
!bootsect将自己移动到0x90000开始的地方,并把setup加载到它的后面.下面程序是再把整个system
!移动到0x0000位置,即把从0x10000到0x8ffff的内存数据块,整块的向内存低端移动了0x10000(64K)
!的位置
			mov ax,#0x0000 !
			cld            !向前移动。设置复制方向
do_move:             !
			mov es,ax      !目的地址 es:di  0x0000:0x0
			add ax,#0x1000 !
			cmp ax,#0x9000 !已经移动完成?
			jz end_move    !
			mov ds,ax      !源地址 ds:si  0x1000:0x0
			sub di,di      !
			sub,si,si      !
			mov cx,#0x8000 !移动0x8000字节
			rep            !
			movsw          !
			jmp do_move    !
!lidt指令用于加载中断描述符表寄存器,它的操作数是6个字节,0-1是描述符表的长度值
!(字节),2-5字节是描述符表的32位线性地址(首地址).中断描述符表中的每一个表项(8字节)
!指出发生中断时需要调用的代码的信息,与中断向量有些相似,但包含更多的信息
!lgdt指令用于加载全局描述符寄存器,其操作数格式与lidt指令相同。全局描述符表中的
!每个描述符项(8字节)描述了保护模式下的数据和代码段的信息。包括段的最大长度限制,段的线性!基址(32位)段特权级,段是否在内存,读写许可以及其他一些保护模式运行的标志
!
end_move:
			mov ax,#SETUPSEG  !
			mov ds,ax         !ds指向本程序段
			lidt idt_48       !加载中断描述符寄存器idt_48是6字节操作数的位置.前2字节表示idt
												!限长,后4字节表示idt表所处的基地址。
			lgdt gdt_48       !加载全局描述符表寄存器
			                  !
			call empty_8042   !等待输入缓冲器空
			mov al,#0xD1      !只有当缓冲器为空时才可以对其写命令
			out 0x64,al       !??8042的p2端口.p2端口的位1用于A20线选通.数据要写到0x60端口
			call empty_8042   !等待输入缓冲器为空,看命令是否被接受
			mov al,#0xDF			!A20 on,选通A20地址线的参数
			out #0x60,al      !
			call empty_8042   !输入缓冲器为空,表示A20线已经选通
			
			mov al,#0x11				!0x11表示初始化命令开始,是ICW1命令字,表示边沿触发 多片级联 最
			out #0x20,al				!后要发送ICW4命令。发送到8259主片
!下面定义的两个字是直接使用机器码表示的两条相对跳转指令,起延时作用。
!0xeb是直接近跳转指令的操作码,带1个字节的相对位移值。因此跳转范围是-127到127.CPU通过吧
!这个相对位移值加到EIP寄存器中就形成一个新的有效地址,此时EIP指向下一条被执行的指令。执
!行时所花费的cpu时钟周期是7-10个。0x00eb表示跳转值是0的一条指令,因此还时直接执行下一条
!指令.这两条指令共可提供17-20个cpu时钟周期的延迟。另外每个空操作指令NOP的时钟周期是3个,
!因此要达到相同的延迟效果就需要6-7个NOP指令
!			.word 0x00eb,0x00eb !jmp $+2,jmp$+2  $表示当前指令地址
			out #0xA0,al        !发送到8259从芯片
			.word 0x00eb,0x00eb !
			mov al,#0x20        !送主芯片ICW2命令字,起始中断号,要送奇地址
			out #0x21,al        !
			.word 0x00eb,0x00eb !
			mov al,#0x28        !送从芯片ICW2命令字,从芯片起始中断号
			out #0xA1,al        !
			.word 0x00eb,0x00eb !
			mov al,#0x04        !主芯片ICW3命令字,
			out #0x21,al        !
			.word 0x00eb,0x00eb !
			mov al,#0x02        !从芯片ICW3
			out #0xA1,al        !
			.word 0x00eb,0x00eb !
			mov al,#0x01        !	主芯片ICW4
			out #0x21,al        !
			.word 0x00eb,0x00eb !
			out #0xA1,al        !从芯片ICW4命令字
			.word 0x00eb,0x0eb  !
			mov al,#0xff        !屏蔽主芯片所有中断请求
			out #0x21,al        !
			.word 0x00eb,0x00eb !
			out #0xA1,al        !屏蔽从片中断请求
			                    !
			mov ax,#0x0001      !保护模式比特位(PE)
			lmsw ax             !加载机器状态字
			jmpi 0,8            !跳转至cs段8,偏移0处
!已经将system模块移动到0x00000开始地方,所以这里的偏移地址是0,这里的段值8已经是保护模式
!下的段选择符了,用于选择描述符表和描述符表项以及所要求的特权级。段选择符长度为16位,
!位0-1表示特权级,位2用于选择全局描述符表(0)还是局部描述符表(1),位3-15是描述符表项的
!索引,指出选择第几项描述符。所以段选择符8(0b0000 0000 0000 1000)表示特权级0,使用全局描!!述符表第一项,该项指出代码的基地址为0,因此这里的跳转指令就会去执行system代码
empty_8042:               !
			.word 0x00eb,0x00eb !
			in al,#0x64         ! 读AT键盘控制器状态寄存器
			test al,#2          !测试第二位,输入缓冲器满
			jnz empty_8042      !
			ret                 !
!全局描述表开始处,描述符表由多个8字节长的描述符表组成。
!这里给出了3个描述符项,第一个无用,但必须存在,第二个是系统代码段描述符,第三项是系统数!据段描述符
gdt:                      !
			.word 0,0,0,0       !
!这里在gdt表中偏移为0x08,加载代码段寄存器时,使用的是这个偏移值
			.word 0x07ff        !8M -limit=2047 
			.word 0x0000        !base address=0
			.word 0x9a00        !code read/exec
			.word 0x00C0        !粒度(granularity)=4096,386
!这里在gdt中偏移值为0x10,加载数据段寄存器时使用这个偏移值
			.word 0x07FF        !8M limit
			.word 0x0000        !base address
			.word 0x9200        !data read/write
			.word 0x00C0        !granularity = 4096 386
idt_48:                   !
			.word 0             ! idt  limit =0 
			.word 0,0           !idt base =0 
gdt_48:                   !
			.word 0x800         !gdt limit=2048,256 GDT entries
													!全局表长度为2k字节,因每8字节组成一个段描述符项
													!所以共有256项
			.word 512+gdt,0x9   !gdt base = 0x9XXXX
													!4个字节构成的内存线性地址0x0009<<16+0x0200+gdt
													!也即0x90200+gdt
.text
endtext:
.data
enddata:
.bss
endbss:





 


setup运行完成后的内存示意图:



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值