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 ( 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) 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 * bytes long. This should be no
  17. ! problem, even in the future. I want to keep it simple. This 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 !子程序调用,读取systemes为参数
  139. call kill_motor
  140.  
  141. ! After that we check which root-device to use. If the device is
  142. ! defined (!= ), nothing is done and the given device is used.
  143. ! Otherwise, either /dev/PS0 (,) or /dev/at0 (,), depending
  144. ! on the number of sectors that the BIOS reports currently.
  145.  
  146. seg cs
  147. mov ax,root_dev
  148. cmp ax,#
  149. jne root_defined
  150. seg cs
  151. mov bx,sectors
  152. mov ax,#0x0208 ! /dev/ps0 - .2Mb
  153. cmp bx,#
  154. je root_defined
  155. mov ax,#0x021c ! /dev/PS0 - .44Mb
  156. cmp bx,#
  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 ,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 +SETUPLEN ! sectors read of current track
  177. ! 开始读取system在磁盘的开始扇区标号
  178. ! :bootsect mbr主引导扇区
  179. ! SETUPLEN:setup所占的扇区数
  180. sread:读取system开始的扇区数
  181. head: .word ! current head
  182. track: .word ! 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,# ! 逻辑左移指令 cx=cx*
  200. add cx,bx
  201. jnc ok2_read
  202. je ok2_read
  203. xor ax,ax
  204. sub ax,bx
  205. shr ax,#
  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,#
  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,#
  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,#
  243. and dx,#0x0100
  244. mov ah,#
  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,#
  253. mov dx,#
  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:

linux kernel 0.11 bootsect的更多相关文章

  1. linux kernel 0.11 head

    head的作用 注意:bootsect和setup汇编采用intel的汇编风格,而在head中,此时已经进入32位保护模式,汇编的采用的AT&T的汇编语言,编译器当然也就变成对应的编译和连接器 ...

  2. Linux内核0.11 bootsect文件说明

    一.总体功能介绍 这是关于Linux-kernel-0.11中boot文件夹下bootsect.s源文件的说明,其中涉及到了一些基础知识可以参考这两篇文章. 操作系统启动过程 软盘相关知识和通过BIO ...

  3. linux kernel 0.11 setup

    setup作用 ①读取参数放在0x90000处. ②将原本在0x10000处的system模块移至0x00000处 ③加载中断描述符表,全局描述符表,进入32位保护模式. 概念 关于实模式和保护模式区 ...

  4. Linux Kernel 4.11首个候选版本开放下载

    Linus Torvalds宣布了即将到来的Linux Kernel 4.11内核分支的首个候选(RC)版本,用户可下载.编译并在自己的GNU/Linux发行版本中进行测试.Linus Torvald ...

  5. Linux Kernel 0.12 启动简介,调试记录(Ubuntu1804, Bochs, gdb)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  6. Linux内核0.11代码阅读(转)

    最近决定开始阅读Linux 0.11的源代码. 学习Linux操作系统的核心概念最好的方法莫过于阅读源代码.而Linux当前最新的源代码包已经有70MB左右,代码十分庞大,要想深入阅读十分困难.而Li ...

  7. Linux内核0.11体系结构 ——《Linux内核完全注释》笔记打卡

    0 总体介绍 一个完整的操作系统主要由4部分组成:硬件.操作系统内核.操作系统服务和用户应用程序,如图0.1所示.操作系统内核程序主要用于对硬件资源的抽象和访问调度. 图0.1 操作系统组成部分 内核 ...

  8. Linux mysql8.0.11安装

    准备:检查是否已安装过mysql,若有便删除(linux系统自带的) rpm -qa | grep mariadb rpm -e nodeps mariadb-libs-5.5.56-2.el7.x8 ...

  9. Linux Kernel 3.11.4/3.10.15/3.4.65/3.0.99

    Linux 今天又发布了4个更新版本,分别是: 3.11.4 2013-10-05 [tar.xz] [pgp] [patch] [view patch] [view inc] [cgit] [cha ...

随机推荐

  1. 将你的代码上传 Bintray 仓库

    在 Android Studio 中,我们通常可以利用 gradle 来导入别人写的第三方库,通常可以简单得使用一句话就能搞定整个导包过程, 比如: compile 'net.cpacm.moneyt ...

  2. 百度地图API 学习网站

    官方示例:http://developer.baidu.com/map/jsdemo.htm#a1_2 (注意:此网页可能由于浏览器问题,源代码编辑器中的代码不能看到.火狐亲测有效) http://d ...

  3. git从入门到精通

    1.git简介 由Linus在2005年花了两周时间完成,也就是开发Linux系统的大神研制. git特点: 自由和开放源码 隐形备份 安全 不需要强大的硬件 更简单的分支 对文件操作容易 2.文件操 ...

  4. com学习(一)GUID 和 接口

    话说在 doc(Word) 复合文件中,已经解决了保存 xls(Excel) 数据的问题了.那么,接下来又要解决另一个问题:当 WORD 程序读取复合文件,遇到了 xls 数据的时候,它该如何启动 E ...

  5. windows 创建服务提示失败 5 拒绝 访问拒绝

    1.桌面创建文本,输入 sc create .....echo. & pause 保存,重命名为   .bat 2.右键该文件,管理员运行

  6. 洛谷P1458 顺序的分数 Ordered Fractions

    P1458 顺序的分数 Ordered Fractions 151通过 203提交 题目提供者该用户不存在 标签USACO 难度普及- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 输入一个 ...

  7. WP8_UTF8 to GB2312转码 (url网址中带中文字符的处理)

    直接使用例如:http://www.abc.php?name=中文符 ,客户端调用,在服务端修改后,会出现乱码, 而windows phone 又不能直接支持gb2312, 经过大量分析和验证,发现 ...

  8. hbase日常运维管用命令,region管理

    1         Hbase日常运维 1.1       监控Hbase运行状况 1.1.1        操作系统 1.1.1.1 IO 群集网络IO,磁盘IO,HDFS IO IO越大说明文件读 ...

  9. 回到顶部js代码

    function go_to_top(){ //把内容滚动指定的像素数(第一个参数是向右滚动的像素数,第二个参数是向下滚动的像素数) window.scrollBy(0,-10); //延时递归调用, ...

  10. dwz简单配置与操作

    1.首先将dwz的文件放到你的项目中(http://yunpan.cn/QbTH4kN6UXX9B) 2.在页面中将前台数据复制到页面中,将js,css等路径配置好 3.这个地方一定要配置好,xml文 ...