歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux0.11內核--啟動引導代碼分析setup.s

Linux0.11內核--啟動引導代碼分析setup.s

日期:2017/3/1 10:24:04   编辑:Linux編程

setup的整體作用:

首先利用BIOS中斷讀取機器的數據,將其保存在地址0x9000:0x0000處,覆蓋了原來bootsect.s代碼所在的位置,由於bootsetc模塊的代

碼運行完畢,已經沒有其他的用處了,所以可以將其覆蓋掉。

然後關閉中斷,setup將system模塊整體移動至內存起始處,原來位於0x1000:0x0000,由於movsb和movsw指令的功能是移動一個字節或

者一個字,源地址由寄存器ds:si指定,目的地址由es:di指定。

指令cld指明di和si的方向是遞增,而std是遞減。

由於system模塊大小超過64K(實模式一個段的最大偏移),而移動指令需要指明段寄存器,所以需要分段移動,下面是移動代碼,代碼語法是

AT&T改寫的

  1. # first we move the system to it's rightful place
  2. mov $0x0000, %ax
  3. cld # 'direction'=0, movs moves forward
  4. do_move:
  5. mov %ax, %es # destination segment
  6. add $0x1000, %ax
  7. cmp $0x9000, %ax
  8. jz end_move
  9. mov %ax, %ds # source segment
  10. sub %di, %di
  11. sub %si, %si
  12. mov $0x8000, %cx
  13. rep
  14. movsw
  15. jmp do_move
  16. # then we load the segment descriptors
  17. end_move:

然後設置數據段寄存器ds並加載中斷描述符和全局描述符

  1. end_move:
  2. mov $SETUPSEG, %ax # right, forgot this at first. didn't work :-)
  3. mov %ax, %ds
  4. lidt idt_48 # load idt with 0,0
  5. lgdt gdt_48 # load gdt with whatever appropriate

lidt和lgdt的操作數是6個字節

第一第二字節表示描述符表的長度值,第三到第六字節表示的是32位的線性基地址(描述符在內存的中的位置)

GDT格式的詳情請見

Linux0.11內核--32位保護模式GDT(全局描述符表)

idt_48和gdt_48的內容如下:

  1. idt_48:
  2. .word 0 # idt limit=0
  3. .word 0,0 # idt base=0L
  4. gdt_48:
  5. .word 0x800 # gdt limit=2048, 256 GDT entries
  6. .word 512+gdt, 0x9 # gdt base = 0X9xxxx,
  7. # 512+gdt is the real gdt after setup is moved to 0x9020 * 0x10

其中gdt_48中第一個字節表示描述符表中的描述符的個數,由於GDT表在內存中占用2KB的內存空間,一個GDT有64位(8個字節),故有256項,後面四個字節表示一個32位的線性地址0x0009<<16+0x0200+gdt

實際就是本程序中的gdt的地址。

Copyright © Linux教程網 All Rights Reserved