3.html

来自「linux 0.11中文版 有注释」· HTML 代码 · 共 351 行 · 第 1/2 页

HTML
351
字号
<html>
<head>
<title>boot/setup.s</title>
<meta name='robots' content='noindex,nofollow'>
<meta name='generator' content='GLOBAL-5.4.1'>
</head>
<body text='#191970' bgcolor='#f5f5dc' vlink='gray'>
<a name='TOP'><h2><a href='../mains.html'>root</a>/<a href='../files/97.html'>boot</a>/setup.s</h2>
<i><font color='green'>/* [&lt;][&gt;][^][v][top]<a href='#BOTTOM'>[bottom]</a><a href='../mains.html'>[index]</a><a href='../help.html'>[help]</a> */</font></i>
<hr>
<pre>
<a name='L1'>!
<a name='L2'>! setup.s (C) 1991 Linus Torvalds
<a name='L3'>!
<a name='L4'>! setup.s is responsible for getting the system data from the BIOS,
<a name='L5'>! and putting them into the appropriate places in system memory.
<a name='L6'>! both setup.s and system has been loaded by the bootblock.
<a name='L7'>!
<a name='L8'>! This code asks the bios for memory/disk/other parameters, and
<a name='L9'>! puts them in a "safe" place: 0x90000-0x901FF, ie where the
<a name='L10'>! boot-block used to be. It is then up to the protected mode
<a name='L11'>! system to read them from there before the area is overwritten
<a name='L12'>! for buffer-blocks.
<a name='L13'>!
<a name='L14'>! setup.s 负责从BIOS 中获取系统数据,并将这些数据放到系统内存的适当地方。
<a name='L15'>! 此时setup.s 和system 已经由bootsect 引导块加载到内存中。
<a name='L16'>!
<a name='L17'>! 这段代码询问bios 有关内存/磁盘/其它参数,并将这些参数放到一个
<a name='L18'>! “安全的”地方:0x90000-0x901FF,也即原来bootsect 代码块曾经在
<a name='L19'>! 的地方,然后在被缓冲块覆盖掉之前由保护模式的system 读取。
<a name='L20'>!
<a name='L21'>
<a name='L22'>! NOTE! These had better be the same as in bootsect.s!
<a name='L23'>! 以下这些参数最好和bootsect.s 中的相同!
<a name='L24'>
<a name='L25'>INITSEG = 0x9000 ! we move boot here - out of the way ! 原来bootsect 所处的段。
<a name='L26'>SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). ! system 在0x10000(64k)处。
<a name='L27'>SETUPSEG = 0x9020 ! this is the current segment ! 本程序所在的段地址。
<a name='L28'>
<a name='L29'>.globl begtext, begdata, begbss, endtext, enddata, endbss
<a name='L30'>.text
<a name='L31'>begtext:
<a name='L32'>.data
<a name='L33'>begdata:
<a name='L34'>.bss
<a name='L35'>begbss:
<a name='L36'>.text
<a name='L37'>
<a name='L38'>entry start
<a name='L39'>start:
<a name='L40'>
<a name='L41'>! ok, the read went well so we get current cursor position and save it for
<a name='L42'>! posterity.
<a name='L43'>! ok,整个读磁盘过程都正常,现在将光标位置保存以备今后使用。
<a name='L44'>
<a name='L45'>mov ax,#INITSEG ! this is done in bootsect already, but...
<a name='L46'>! 将ds 置成#INITSEG(0x9000)。这已经在bootsect 程序中
<a name='L47'>! 设置过,但是现在是setup 程序,Linus 觉得需要再重新
<a name='L48'>! 设置一下。
<a name='L49'>mov ds,ax
<a name='L50'>mov ah,#0x03 ! read cursor pos
<a name='L51'>! BIOS 中断0x10 的读光标功能号 ah = 0x03
<a name='L52'>! 输入:bh = 页号
<a name='L53'>! 返回:ch = 扫描开始线,cl = 扫描结束线,
<a name='L54'>! dh = 行号(0x00 是顶端),dl = 列号(0x00 是左边)。
<a name='L55'>xor bh,bh
<a name='L56'>int 0x10 ! save it in known place, con_init fetches
<a name='L57'>mov [0],dx ! it from 0x90000.
<a name='L58'>! 上两句是说将光标位置信息存放在0x90000 处,控制台
<a name='L59'>! 初始化时会来取。
<a name='L60'>
<a name='L61'>! Get memory size (extended mem, kB) ! 下面3 句取扩展内存的大小值(KB)。
<a name='L62'>! 是调用中断0x15,功能号ah = 0x88
<a name='L63'>! 返回:ax = 从0x100000(1M)处开始的扩展内存大小(KB)。
<a name='L64'>! 若出错则CF 置位,ax = 出错码。
<a name='L65'>
<a name='L66'>mov ah,#0x88
<a name='L67'>int 0x15
<a name='L68'>mov [2],ax ! 将扩展内存数值存在0x90002 处(1 个字)。
<a name='L69'>
<a name='L70'>! Get video-card data: ! 下面这段用于取显示卡当前显示模式。
<a name='L71'>! 调用BIOS 中断0x10,功能号 ah = 0x0f
<a name='L72'>! 返回:ah = 字符列数,al = 显示模式,bh = 当前显示页。
<a name='L73'>! 0x90004(1 字)存放当前页,0x90006 显示模式,0x90007 字符列数。
<a name='L74'>
<a name='L75'>mov ah,#0x0f
<a name='L76'>int 0x10
<a name='L77'>mov [4],bx ! bh = display page
<a name='L78'>mov [6],ax ! al = video mode, ah = window width
<a name='L79'>
<a name='L80'>! check for EGA/VGA and some config parameters ! 检查显示方式(EGA/VGA)并取参数。
<a name='L81'>! 调用BIOS 中断0x10,附加功能选择 -取方式信息
<a name='L82'>! 功能号:ah = 0x12,bl = 0x10
<a name='L83'>! 返回:bh = 显示状态
<a name='L84'>! (0x00 - 彩色模式,I/O 端口=0x3dX)
<a name='L85'>! (0x01 - 单色模式,I/O 端口=0x3bX)
<a name='L86'>! bl = 安装的显示内存
<a name='L87'>! (0x00 - 64k, 0x01 - 128k, 0x02 - 192k, 0x03 = 256k)
<a name='L88'>! cx = 显示卡特性参数(参见程序后的说明)。
<a name='L89'>
<a name='L90'>mov ah,#0x12
<a name='L91'>mov bl,#0x10
<a name='L92'>int 0x10
<a name='L93'>mov [8],ax ! 0x90008 = ??
<a name='L94'>mov [10],bx ! 0x9000A = 安装的显示内存,0x9000B = 显示状态(彩色/单色)
<a name='L95'>mov [12],cx ! 0x9000C = 显示卡特性参数。
<a name='L96'>
<a name='L97'>! Get hd0 data ! 取第一个硬盘的信息(复制硬盘参数表)。
<a name='L98'>! 第1 个硬盘参数表的首地址竟然是中断向量0x41 的向量值!而第2 个硬盘
<a name='L99'>! 参数表紧接第1 个表的后面,中断向量0x46 的向量值也指向这第2 个硬盘
<a name='L100'>! 的参数表首址。表的长度是16 个字节(0x10)。
<a name='L101'>! 下面两段程序分别复制BIOS 有关两个硬盘的参数表,0x90080 处存放第1 个
<a name='L102'>! 硬盘的表,0x90090 处存放第2 个硬盘的表。
<a name='L103'>
<a name='L104'>mov ax,#0x0000
<a name='L105'>mov ds,ax
<a name='L106'>lds si,[4*0x41] ! 取中断向量0x41 的值,也即hd0 参数表的地址??ds:si
<a name='L107'>mov ax,#INITSEG
<a name='L108'>mov es,ax
<a name='L109'>mov di,#0x0080 ! 传输的目的地址: 0x9000:0x0080 ?? es:di
<a name='L110'>mov cx,#0x10 ! 共传输0x10 字节。
<a name='L111'>rep
<a name='L112'>movsb
<a name='L113'>
<a name='L114'>! Get hd1 data
<a name='L115'>
<a name='L116'>mov ax,#0x0000
<a name='L117'>mov ds,ax
<a name='L118'>lds si,[4*0x46] ! 取中断向量0x46 的值,也即hd1 参数表的地址??ds:si
<a name='L119'>mov ax,#INITSEG
<a name='L120'>mov es,ax
<a name='L121'>mov di,#0x0090 ! 传输的目的地址: 0x9000:0x0090 ?? es:di
<a name='L122'>mov cx,#0x10
<a name='L123'>rep
<a name='L124'>movsb
<a name='L125'>
<a name='L126'>! Check that there IS a hd1 :-) ! 检查系统是否存在第2 个硬盘,如果不存在则第2 个表清零。
<a name='L127'>! 利用BIOS 中断调用0x13 的取盘类型功能。
<a name='L128'>! 功能号 ah = 0x15;
<a name='L129'>! 输入:dl = 驱动器号(0x8X 是硬盘:0x80 指第1 个硬盘,0x81 第2 个硬盘)
<a name='L130'>! 输出:ah = 类型码;00 --没有这个盘,CF 置位; 01 --是软驱,没有change-line 支持;
<a name='L131'>! 02 --是软驱(或其它可移动设备),有change-line 支持; 03 --是硬盘。
<a name='L132'>
<a name='L133'>mov ax,#0x01500
<a name='L134'>mov dl,#0x81
<a name='L135'>int 0x13
<a name='L136'>jc no_disk1
<a name='L137'>cmp ah,#3 ! 是硬盘吗?(类型 = 3 ?)。
<a name='L138'>je is_disk1
<a name='L139'>no_disk1:
<a name='L140'>mov ax,#INITSEG ! 第2 个硬盘不存在,则对第2 个硬盘表清零。
<a name='L141'>mov es,ax
<a name='L142'>mov di,#0x0090
<a name='L143'>mov cx,#0x10
<a name='L144'>mov ax,#0x00
<a name='L145'>rep
<a name='L146'>stosb
<a name='L147'>is_disk1:
<a name='L148'>
<a name='L149'>! now we want to move to protected mode ... ! 从这里开始我们要保护模式方面的工作了。
<a name='L150'>
<a name='L151'>cli ! no interrupts allowed ! ! 此时不允许中断。
<a name='L152'>
<a name='L153'>! first we move the system to it's rightful place
<a name='L154'>! 首先我们将system 模块移到正确的位置。
<a name='L155'>! bootsect 引导程序是将system 模块读入到从0x10000(64k)开始的位置。由于当时假设
<a name='L156'>! system 模块最大长度不会超过0x80000(512k),也即其末端不会超过内存地址0x90000,
<a name='L157'>! 所以bootsect 会将自己移动到0x90000 开始的地方,并把setup 加载到它的后面。
<a name='L158'>! 下面这段程序的用途是再把整个system 模块移动到0x00000 位置,即把从0x10000 到0x8ffff
<a name='L159'>! 的内存数据块(512k),整块地向内存低端移动了0x10000(64k)的位置。
<a name='L160'>
<a name='L161'>mov ax,#0x0000
<a name='L162'>cld ! 'direction'=0, movs moves forward
<a name='L163'>do_move:
<a name='L164'>mov es,ax ! destination segment ! es:di??目的地址(初始为0x0000:0x0)
<a name='L165'>add ax,#0x1000

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?