linux kernel 0.11 bootsect

 

bootsect作用

 

①将自己移动到0x90000处

 

②将setup从磁盘读到0x90200处

 

③将system从磁盘读到0x10000处

 

寄存器

汇编代码中存在:数据段data seg  栈段 stack seg 

汇编代码中的寄存器概念:

第一组:

  DS:数据段寄存器  ES:额外数据段寄存器

  SS:栈段寄存器   

  SI:源索引寄存器  DI:目的索引寄存器

  通常 DS:SI和ES:DI配对时通常用来执行一些数据段字符串操作.

  SI和DI两个寄存器叫做索引寄存器, 这两个寄存器通常用来处理数组或字符串.

第二组:

  BP(base pointer), SP(Stack Pointer), 和IP(Instriction pointer)叫做指针寄存器.

  BP:基指针     SP:栈指针    IP:指令指针

  通常BP用来保存使用局部变量的地址.

  SP用来指向当前的栈. 尽管SP可以被很容易地修改, 你还是一定要非常小心. 因为如果这个寄存器搞错了, 你的程序就毁了.

  IP用来指示当前运行程序的当前指针. 通常和CS一起使用, IP是不允许修改的.

 中断

系统中断分为BIOS中断和系统中断。所以就存在两个中断向量表。

其中BIOS中断的int 0x13是磁盘I/O中断。

 

汇编中的字符串操作

(1) lodsb、lodsw:把DS:SI指向的存储单元中的数据装入AL或AX,然后根据DF标志增减SI(CLD递增, STD递减)
(2) stosb、stosw:把AL或AX中的数据装入ES:DI指向的存储单元,然后根据DF标志增减DI(CLD递增, STD递减)
(3) movsb、movsw:把DS:SI指向的存储单元中的数据装入ES:DI指向的存储单元中,然后根据DF标志分别增减SI和DI
(4) scasb、scasw:把AL或AX中的数据与ES:DI指向的存储单元中的数据相减,影响标志位,然后根据DF标志分别增减SI和DI
(5) cmpsb、cmpsw:把DS:SI指向的存储单元中的数据与ES:DI指向的存储单元中的数据相减,影响标志位,然后根据DF标志分别增减SI和DI
(6) rep:重复其后的串操作指令。重复前先判断CX是否为0,为0就结束重复,否则CX减1,重复其后的串操作指令。 主要用在MOVS和STOS前。一般不用在LODS前。

  上述指令涉及的寄存器:段寄存器DS和ES、变址寄存器SI和DI、累加器AX、计数器CX
      涉及的标志位:DF、AF、CF、OF、PF、SF、ZF

搬移字串指令有两种,分别是 MOVSB 和 MOVSW,先说 MOVSB。MOVSB 的英文是 move string byte,意思是搬移一个字节,它是把 DS:SI 所指地址的一个字节搬移到 ES:DI 所指的地址上,搬移后原来的内容不变,但是原来 ES:DI 所指的内容会被覆盖而且在搬移之后SI 和 DI 会自动地址向下一个要搬移的地址。

一般而言,通常程序设计师一般并不会只搬一个字节,通常都会重复许多次,如果要重复的话,就得把重复次数 ( 也就是字串长度 ) 先记录在 CX 寄存器,并且在 MOVSB 之前加上 REP 指令,REP 是重复 (repeat) 的意思。这种写法很是奇怪,一般而言汇编语言源文件的每一行都只有一个指令,但 REP MOVSB 却可以在同一行写两个指令,当然分开写也是一样的。

1、操作指令功能
   移动 movsb, movsw, movsd   从 ESI 指向的内存位置向 EDI 指向的内存位置拷贝数据  
   比较 cmpsb, cmpsw, cmpsd   把 ESI 指向内存位置的数据和 EDI 指向内存位置拷的数据比较(ESI,EDI都指向相匹配元素的后面的那个元素) 
   搜索 scasb, scasw, scasd   把 al/ax/eax 中的数据与 EDI 寻址的内存数据比较(EDI指向查找到的元素的后面的那个元素) 
   储存 stosb, stosw, stosd   把 al/ax/eax 中的数据保存在 EDI 寻址的内存单元  
   加载 lodsb, lodsw, lodsd   把 ESI 寻址的内存数据加载到 al/ax/eax 中

2、重复执行前缀
   rep           当 ecx>0 时重复  
   repe, repz    当 ecx>0 ,且 ZF==1 时重复(只用在比较和搜索中)  
   repne,repnz   当 ecx>0 ,且 ZF==0 时重复(只用在比较和搜索中)
  
3、重复执行方向
   cld    清除 DF 标志,ESI 和 EDI  递增  
   std    设置 DF 标志,ESI 和 EDI  递减
  
4、字符操作指令格式
   方向               cld, std  
   数据来源             esi,al/ax/eax  
   数据目的             edi,al/ax/eax  
   循环次数             ecx  
   重复前缀 操作指令  rep, repe, repne  movsb, cmpsb, scasb, stosb, lodsb

bootsect源代码注释

 

  1 !
  2 ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
  3 ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
  4 ! versions of linux
  5 !
  6 SYSSIZE = 0x3000            !system模块的大小
  7 !
  8 !    bootsect.s        (C) 1991 Linus Torvalds
  9 !
 10 ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
 11 ! iself out of the way to address 0x90000, and jumps there.
 12 !
 13 ! It then loads 'setup' directly after itself (0x90200), and the system
 14 ! at 0x10000, using BIOS interrupts. 
 15 !
 16 ! NOTE! currently system is at most 8*65536 bytes long. This should be no
 17 ! problem, even in the future. I want to keep it simple. This 512 kB
 18 ! kernel size should be enough, especially as this doesn't contain the
 19 ! buffer cache as in minix
 20 !
 21 ! The loader has been made as simple as possible, and continuos
 22 ! read errors will result in a unbreakable loop. Reboot by hand. It
 23 ! loads pretty fast by getting whole sectors at a time whenever possible.
 24 
 25 .globl begtext, begdata, begbss, endtext, enddata, endbss    !全局标识符
 26 .text                        !文本段
 27 begtext:                
 28 .data                        !数据段
 29 begdata:                
 30 .bss                        !堆栈段
 31 begbss:
 32 .text
 33 
 34 SETUPLEN = 4                ! nr of setup-sectors    setup程序的扇区数
 35 BOOTSEG  = 0x07c0            ! original address of boot-sector    
 36 INITSEG  = 0x9000            ! we move boot here - out of the way
 37 SETUPSEG = 0x9020            ! setup starts here
 38 SYSSEG   = 0x1000            ! system loaded at 0x10000 (65536).
 39 ENDSEG   = SYSSEG + SYSSIZE        ! where to stop loading
 40                                                             !    从0x10000加载system模块,大小为
 41 ! ROOT_DEV:    0x000 - same type of floppy as boot.
 42 !        0x301 - first partition on first drive etc
 43 ROOT_DEV = 0x306                            !根文件系统的在第二盘第一分区上
 44 
 45 entry start                                        !连接程序从start处开始执行
 46 start:
 47                                                             ! 47--56 行作用是将自身(bootsect) 从目前段位置 0x07c0(31k)
 48                                                             ! 移动到 0x9000(576k)处,共 256 字(512 字节),然后跳转到
 49                                                           ! 移动后代码的 go 标号处,也即本程序的下一语句处。
 50     mov    ax,#BOOTSEG
 51     mov    ds,ax                                        !    ds=07c0
 52     mov    ax,#INITSEG
 53     mov    es,ax                                        !    es=9000
 54     mov    cx,#256                                    !    cx=256=bootsect大小
 55     sub    si,si
 56     sub    di,di
 57     rep                                                    !    rep movb或rep movw根据cx的值,重复执行串传送指令
 58     movw                                                !    movw,串传送指令,将ds:si指向的内存单元的字数据送入到es:di中,将si和di增2
 59     jmpi    go,INITSEG                        !    jmp是段内跳转指令,而jmpi是段间跳转指令,所以需要提供段地址(第二个操作数)。
 60                                                             !    即jmpi的第一个操作数是段内偏移地址;第二个是跳转到的段地址。
 61 go:    mov    ax,cs                                    !    CS存放指令的段地址,此时已经为9000,IP存放指令的偏移地址。
 62     mov    ds,ax                                        !    将ds    es    ss指向新的代码段
 63     mov    es,ax                                        !    因为程序设计堆栈操作,所以必须设置堆栈
 64 ! put stack at 0x9ff00.
 65     mov    ss,ax
 66     mov    sp,#0xFF00        ! arbitrary value >>512
 67                                                             ! ?
 68                                                             !    栈指针指向9ff00处,因为90200处放setup,setup大约占4个扇区
 69                                                             !    所以sp指向,(200+200*4+堆栈大小)之外
 70 ! load the setup-sectors directly after the bootblock.
 71 ! Note that 'es' is already set up.
 72 
 73 load_setup:                                        !    cs指令的段基址+ip就指向了这里。
 74                                                             ! 68--77 行的用途是利用 BIOS 中断 INT 0x13 将 setup 模块从磁盘第 2 个扇区  
 75                                                             ! 开始读到 0x90200 开始处,共读 4 个扇区。如果读出错,则复位驱动器,并    
 76                                                             ! 重试,没有退路。INT 0x13 的使用方法如下:                               
 77                                                             ! 读扇区:                                                                
 78                                                             ! ah = 0x02 - 读磁盘扇区到内存;al = 需要读出的扇区数量;                 
 79                                                             ! ch = 磁道(柱面)号的低 8 位; cl = 开始扇区(0-5 位),磁道号高 2 位(6-7);
 80                                                             ! dh = 磁头号; dl = 驱动器号(如果是硬盘则要置位 7);                   
 81                                                             ! es:bx 指向数据缓冲区; 如果出错则 CF 标志置位。 
 82                                                             !    INT 13h / AH = 02h - read disk sectors into memory.
 83                                                             !    input:
 84                                                             !    AL = number of sectors to read/write (must be nonzero)
 85                                                             !    CH = cylinder number (0..79).
 86                                                             !    CL = sector number (1..18).
 87                                                             !    DH = head number (0..1).
 88                                                             !    DL = drive number (0..3 , depends on quantity of FLOPPY_? files).
 89                                                             !    ES:BX points to data buffer.
 90                                                             !    return:
 91                                                             !    CF set on error.
 92                                                             !    CF clear if successful.
 93                                                             !    AH = status (0 - if successful).
 94                                                             !    AL = number of sectors transferred. 
 95                                                             !    Note: each sector has 512 bytes.  
 96                                                             !    将从0磁道第二2扇区开始,读取4个扇区的数据到ES:BX指定的内存中。                     
 97     mov    dx,#0x0000        ! drive 0, head 0                        dx=dl+dh
 98     mov    cx,#0x0002        ! sector 2, track 0                    cx=cl+ch
 99     mov    bx,#0x0200        ! address = 512, in INITSEG    es+bx=090200,
100     mov    ax,#0x0200+SETUPLEN    ! service 2, nr of sectors    读磁盘的位置+读取的扇区数目
101     int    0x13            ! read it            产生中断,AH为入口参数,将数据读入,读取完毕!加载setup完毕!
102     jnc    ok_load_setup        ! ok - continue    跳转 有添加跳转,如果中断操作成功,则输出system loading....
103     mov    dx,#0x0000            !    否则复位磁盘,重新读取setup模块
104     mov    ax,#0x0000        ! reset the diskette    复位磁盘
105     int    0x13
106     j    load_setup            !    无条件跳转
107 
108 ok_load_setup:                                !?
109 
110 ! Get disk drive parameters, specifically nr of sectors/track
111 
112     mov    dl,#0x00
113     mov    ax,#0x0800        ! AH=8 is get drive parameters
114     int    0x13
115     mov    ch,#0x00
116     seg cs
117     mov    sectors,cx
118     mov    ax,#INITSEG
119     mov    es,ax
120 
121 ! Print some inane message
122 
123     mov    ah,#0x03        ! read cursor pos
124     xor    bh,bh
125     int    0x10
126     
127     mov    cx,#24
128     mov    bx,#0x0007        ! page 0, attribute 7 (normal)
129     mov    bp,#msg1            !    显示加载system
130     mov    ax,#0x1301        ! write string, move cursor
131     int    0x10
132 
133 ! ok, we've written the message, now
134 ! we want to load the system (at 0x10000)
135 
136     mov    ax,#SYSSEG
137     mov    es,ax        ! segment of 0x010000
138     call    read_it            !子程序调用,读取system,es为参数
139     call    kill_motor
140 
141 ! After that we check which root-device to use. If the device is
142 ! defined (!= 0), nothing is done and the given device is used.
143 ! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
144 ! on the number of sectors that the BIOS reports currently.
145 
146     seg cs
147     mov    ax,root_dev
148     cmp    ax,#0
149     jne    root_defined
150     seg cs
151     mov    bx,sectors
152     mov    ax,#0x0208        ! /dev/ps0 - 1.2Mb
153     cmp    bx,#15
154     je    root_defined
155     mov    ax,#0x021c        ! /dev/PS0 - 1.44Mb
156     cmp    bx,#18
157     je    root_defined
158 undef_root:
159     jmp undef_root
160 root_defined:
161     seg cs
162     mov    root_dev,ax
163 
164 ! after that (everyting loaded), we jump to
165 ! the setup-routine loaded directly after
166 ! the bootblock:
167 
168     jmpi    0,SETUPSEG
169 
170 ! This routine loads the system at address 0x10000, making sure
171 ! no 64kB boundaries are crossed. We try to load it as fast as
172 ! possible, loading whole tracks whenever we can.
173 !
174 ! in:    es - starting address segment (normally 0x1000)
175 !
176 sread:    .word 1+SETUPLEN    ! sectors read of current track    
177                                                     !    开始读取system在磁盘的开始扇区标号
178                                                     !    1:bootsect mbr主引导扇区
179                                                     !    SETUPLEN:setup所占的扇区数
180                                                     !sread:读取system开始的扇区数
181 head:    .word 0            ! current head
182 track:    .word 0            ! current track
183 
184 read_it:
185     mov ax,es
186     test ax,#0x0fff        !    0x1000&&0x0ffff
187 die:    jne die            ! es must be at 64kB boundary    如果不在0x10000处,则进入死循环
188     xor bx,bx        ! bx is starting address within segment
189 rp_read:
190     mov ax,es
191     cmp ax,#ENDSEG        ! have we loaded all yet?
192     jb ok1_read                !    如果未结束,继续读取
193     ret
194 ok1_read:
195     seg cs                        !    不想使用默认的段地址寄存器,那么你可以强制指定一个段地址寄存器
196     mov ax,sectors        !    读取磁道的扇区数
197     sub ax,sread            !    减去已读的磁道扇区数
198     mov cx,ax                    !    cx=未读的扇区数
199     shl cx,#9                    !    逻辑左移指令    cx=cx*512
200     add cx,bx                    
201     jnc ok2_read
202     je ok2_read
203     xor ax,ax
204     sub ax,bx
205     shr ax,#9
206 ok2_read:
207     call read_track
208     mov cx,ax
209     add ax,sread
210     seg cs
211     cmp ax,sectors
212     jne ok3_read
213     mov ax,#1
214     sub ax,head
215     jne ok4_read
216     inc track
217 ok4_read:
218     mov head,ax
219     xor ax,ax
220 ok3_read:
221     mov sread,ax
222     shl cx,#9
223     add bx,cx
224     jnc rp_read
225     mov ax,es
226     add ax,#0x1000
227     mov es,ax
228     xor bx,bx
229     jmp rp_read
230 
231 read_track:
232     push ax
233     push bx
234     push cx
235     push dx
236     mov dx,track
237     mov cx,sread
238     inc cx
239     mov ch,dl
240     mov dx,head
241     mov dh,dl
242     mov dl,#0
243     and dx,#0x0100
244     mov ah,#2
245     int 0x13
246     jc bad_rt
247     pop dx
248     pop cx
249     pop bx
250     pop ax
251     ret
252 bad_rt:    mov ax,#0
253     mov dx,#0
254     int 0x13
255     pop dx
256     pop cx
257     pop bx
258     pop ax
259     jmp read_track
260 
261 !/*
262 ! * This procedure turns off the floppy drive motor, so
263 ! * that we enter the kernel in a known state, and
264 ! * don't have to worry about it later.
265 ! */
266 kill_motor:
267     push dx
268     mov dx,#0x3f2
269     mov al,#0
270     outb
271     pop dx
272     ret
273 
274 sectors:
275     .word 0
276 
277 msg1:
278     .byte 13,10
279     .ascii "Loading system ..."
280     .byte 13,10,13,10
281 
282 .org 508
283 root_dev:
284     .word ROOT_DEV
285 boot_flag:
286     .word 0xAA55
287 
288 .text
289 endtext:
290 .data
291 enddata:
292 .bss
293 endbss:

 

posted @ 2015-08-23 11:54  陈贞  阅读(133)  评论(0编辑  收藏  举报