ubuntu下安裝bochs而且運行linux0.00

ubuntu下安裝bochslinux

安裝gcc編譯環境ios

sudo apt-get install build-essentialgit

sudo apt-get install xorg-dev
sudo apt-get install fort77
sudo apt-get install libgtk2.0-dev
sudo apt-get install libwxgtk3.0-devgithub

下載bochs最新版本
http://bochs.sourceforge.net/ubuntu

wget https://nchc.dl.sourceforge.net/project/bochs/bochs/2.6.9/bochs-2.6.9.tar.gzapp

安裝命令
清理:
sudo rm -rf /opt/local/bin/*
sudo rm -rf /opt/local/share/bochsoop

$tar vxzf bochs-2.6.9.tar.gz
$cd bochs-2.6.9
$./configure --enable-debugger --enable-disasm
$ ./configure --with-x11 --with-wx --enable-debugger --enable-disasm --enable-all-optimizations --enable-readline --enable-long-phy-address --enable-debugger-gui --prefix=/opt/localui

修改Makefile(新版不須要)
LIBS =  
 -lz -lrt -lm -lpthread 操作系統

$make
$cp bochs bochsdbg
$sudo make install.net

安裝nasm
sudo apt-get install nasm


編譯boot.asm
nasm boot.asm -o boot.bin

此處的boot.asm是一段彙編代碼,在屏幕上打印出hello, OS world!

代碼以下:

org 07c00h ; 告訴編譯器程序加載到7c00處
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ; 調用顯示字符串例程
jmp $ ; 無限循環
DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, 16 ; CX = 串長度
mov ax, 01301h ; AH = 13,  AL = 01h
mov bx, 000ch ; 頁號爲0(BH = 0) 黑底紅字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 10h 號中斷
ret
BootMessage: db "Hello, OS world!"
times 510-($-$$) db 0 ; 填充剩下的空間,使生成的二進制代碼剛好爲512字節
dw 0xaa55 ; 結束標誌

用bximage命令來建立img文件

$ bximage
========================================================================
                                bximage
  Disk Image Creation / Conversion / Resize and Commit Tool for Bochs
         $Id: bximage.cc 13069 2017-02-12 16:51:52Z vruppert $
========================================================================

1. Create new floppy or hard disk image
2. Convert hard disk image to other format (mode)
3. Resize hard disk image
4. Commit 'undoable' redolog to base image
5. Disk image info

0. Quit

Please choose one [0] 1

Create image

Do you want to create a floppy disk image or a hard disk image?
Please type hd or fd. [hd] fd

Choose the size of floppy disk image to create.
Please type 160k, 180k, 320k, 360k, 720k, 1.2M, 1.44M, 1.68M, 1.72M, or 2.88M.
 [1.44M] 

What should be the name of the image?
[a.img] 

Creating floppy image 'a.img' with 2880 sectors

The following line should appear in your bochsrc:
  floppya: image="a.img", status=inserted

使用dd命令將它寫進剛剛建立的軟盤映像a.img的第一個扇區
dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc

此時還須要配置bochs的配置文件bochsrc,標準的配置文件格式爲

###############################################################
# Configuration file for Bochs
###############################################################

# how much memory the emulated machine will have
 megs: 32

# filename of ROM images
 romimage: file=/opt/local/share/bochs/BIOS-bochs-latest #/opt/share/bochs/BIOS-bochs-latest
 vgaromimage: file=/opt/local/share/bochs/VGABIOS-lgpl-latest #/usr/share/vgabios/vgabios.bin

# what disk images will be used
 floppya: 1_44=a.img, status=inserted

# choose the boot disk.
 boot: floppy

# where do we send log messages?
# log: bochsout.txt

# disable the mouse
 mouse: enabled=0

# enable key mapping, using US layout as default.
# keyboard_mapping: enabled=1, map=/opt/local/share/bochs/keymaps/x11-pc-us.map
  keyboard: keymap=/opt/local/share/bochs/keymaps/x11-pc-us.map

 

接着即可以執行

bochs -f bochsrc
來運行bochsrc虛擬機。

nasm彙編直接生成可啓動的軟盤鏡像(根據30天自制操做系統)

; hello-os
; TAB=4
		DB		0xeb, 0x4e, 0x90
		DB		"HELLOIPL"		;
		DW		512				;
		DB		1				;
		DW		1				;
		DB		2				;
		DW		224				;
		DW		2880			;
		DB		0xf0			;
		DW		9				;
		DW		18				;
		DW		2				;
		DD		0				;
		DD		2880			;
		DB		0,0,0x29		;
		DD		0xffffffff		;
		DB		"HELLO-OS   "	;
		DB		"FAT12   "		;
		times	18 db 0			;
;

		DB		0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c
		DB		0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a
		DB		0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09
		DB		0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb
		DB		0xee, 0xf4, 0xeb, 0xfd

;

		DB		0x0a, 0x0a		;
		DB		"hello, world"
		DB		0x0a			;
		DB		0
		times 510-($-$$) db 0
		DB		0x55, 0xaa

;

		DB		0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
		
		times	4600 db 0			;
		DB		0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
		times	1469432 db 0			;

 nasm -o helloos.img helloos.asm 

生成的img大小和1.4M軟盤一致。能夠直接啓動

; hello-os
; TAB=4

		ORG		0x7c00			;

;

		JMP SHORT entry
		DB		0x90
		DB		"HELLOIPL"		;
		DW		512				;
		DB		1				;
		DW		1				;
		DB		2				;
		DW		224				;
		DW		2880			;
		DB		0xf0			;
		DW		9				;
		DW		18				;
		DW		2				;
		DD		0				;
		DD		2880			;
		DB		0,0,0x29		;
		DD		0xffffffff		;
		DB		"HELLO-OS   "	;
		DB		"FAT12   "		;

;

entry:
		MOV		AX,0			;
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX
		MOV		ES,AX

		MOV		SI,msg
putloop:
		MOV		AL,[SI]
		ADD		SI,1			;
		CMP		AL,0
		JE		fin
		MOV		AH,0x0e			;
		MOV		BX,15			;
		INT		0x10			;
		JMP		putloop
fin:
		HLT						;
		JMP		fin				;

msg:
		DB		0x0a, 0x0a		;
		DB		"hello,myworld"
		DB		0x0a			;
		DB		0
		times 510-($-$$) db 0
		DB		0x55, 0xaa

;

		DB		0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
		times	4600 db 0			;
		DB		0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
		times	1469432 db 0			;

===========================================================

運行linux0.00

克隆項目到本地硬盤

git clone https://github.com/voidccc/linux0.00.git

cd linux0.00

生成軟盤映像a.img(bximage)

修改Makefile以下

# Makefile for linux 0.00

all: disk

disk: boot head
	dd bs=32 if=boot of=a.img skip=1
	dd bs=512 if=head of=a.img skip=8 seek=1

boot: boot.s
	as86 -0 -a -o boot.o boot.s
	ld86 -0 -s -o boot boot.o
head: head.s
	as --32 -o head.o head.s
	ld -m elf_i386 -Ttext 0 -e startup_32 -o head head.o
clean:
	rm -f core boot *.o head

主要改變:as改了as --32,不然在64位系統中不能彙編,另外在原項目中直接寫到映像文件Image,的到的文件大小6k多雖然也能在bochs中啓動,但不是標準的軟盤映像,這裏用a.img代替

修改.bochsrc(根據bochs安裝位置)

###############################################################
# Configuration file for Bochs
###############################################################

# how much memory the emulated machine will have
 megs: 32

# filename of ROM images
 romimage: file=/opt/local/share/bochs/BIOS-bochs-latest #/opt/share/bochs/BIOS-bochs-latest
 vgaromimage: file=/opt/local/share/bochs/VGABIOS-lgpl-latest #/usr/share/vgabios/vgabios.bin

# what disk images will be used
floppya: 1_44=a.img, status=inserted
#ata0-master: type=disk, path="hdc.img", mode=flat, cylinders=410, heads=16, spt=38
# choose the boot disk.
 boot: a

# where do we send log messages?
# log: bochsout.txt

# disable the mouse
 mouse: enabled=0

# enable key mapping, using US layout as default.
# keyboard_mapping: enabled=1, map=/opt/local/share/bochs/keymaps/x11-pc-us.map
  keyboard: keymap=/opt/local/share/bochs/keymaps/x11-pc-us.map

 $ cat boot.s 

! voidccc created 20120913

! 本文件編譯方法
! as86 -0 -a -o boot.o boot.s
! ld86 -0 -s -o boot boot.o

! 說明

! 這是512K的引導扇區,作了以下的工做:
! 1 使用BIOS的0x13中斷,讀取真正內核到內存
! 2 將內核移動到內存開始位置
! 3 設置保護模式下的初始GDT/IDT
! 4 切換到保護模式
! 5 跳轉到內核開始位置執行
!mov cx,#0x2000 here need modify

BOOTSEG = 0x07c0 
SYSSEG = 0x1000         !內核先被加載到的位置
SYSLEN = 17             !內核佔用的磁盤扇區數,在使用int 13讀取內核時用到
entry start             !入口點
start:
    jmpi go,#BOOTSEG    !段間跳轉到
!BIOS已經將本程序加載到0x07c0的位置,目前是在實模式下,啓動時段寄存器的缺省值是00,因此這句實際仍是跳轉到go,0的位置,同時段間跳轉會修改CS和IP的值,這句執行完後,CS被設置爲0x07c0,IP被設置爲go
go:
    mov ax,cs           !讓DS和SS都指向0x07c0段,由於段寄存器只能接受寄存器的
    mov ds,ax
    mov ss,ax
    mov sp,#0x400
!使用BIOS中斷調用加載內核代碼到0x10000處,BIOS的0x13中斷具體使用方式此處不作深究。
!只要知道實模式下初始的中斷向量表是在跳轉到0x07c0以前,已經由BIOS設置好就行。
load_system:
    mov dx,#0x0000
    mov cx,#0x0002
    mov ax,#SYSSEG
    mov es,ax
    xor bx,bx           ! 清空bx,ES:BX(0x10000:0x0000)是讀入緩衝區位置
    mov ax,#0x200+SYSLEN
    int 0x13
    jnc ok_load         !若沒有發生錯誤則跳轉繼續運行,不然死循環
die: jmp die
ok_load:
    cli                 !關閉中斷,之因此要關閉中斷,是由於此時已經將內核加載完畢,而加載內核是須要使用BIOS提供的0x13中斷的,因此在加載完內核前不能關閉中斷。然後續要轉入保護模式而且使用多任務,在內核徹底準備好後續操做前,要將中斷關閉。不然中斷會破壞內核的初始化。後續再開啓多任務時,會再次開啓中斷。
    mov ax,#SYSSEG      !爲rep指令作準備,把要內核要開始移動的位置,放入DS:SI,目的地位置放入ES:DI,移動次數放入cx,cx是移動次數4096(0x1000轉換爲10進制)次
    mov ds,ax
    xor ax,ax
    mov es,ax
    mov cx,#0x2000
    sub si,si
    sub di,di
    rep
    movw                !每次移動一個字
!加載IDT和GDT基地址寄存器IDTR和GDTR
!由於剛使用了ds,如今要先回復ds
    mov ax,#BOOTSEG
    mov ds,ax
    lidt idt_48         !加載idt,給保護模式用的,48位
    lgdt gdt_48         !加載gdt,給保護模式用的,48位

!設置CR0中的PE位,進入保護模式
    mov ax,#0x0001
    lmsw ax             !將ax放入CR0
!雖然執行LMSW指令之後切換到了保護模式,但該指令規定其後必須緊隨一條段間跳轉指令以
!刷新CPU的指令緩衝隊列。所以在LMSW指令後,CPU仍是繼續執行下一條指令
!此處0,8已是保護模式的地址,8是選擇符,0是偏移地址
!跳轉到段選擇符是8,偏移0的地址處,段選擇符8轉化爲16位2進製爲
!0000000000001        0          00
!|--描述符索引--|--GDT/LDT--|--特權級--|
!其中0爲GDT 1爲LDT
!其中00爲特權級0 11爲特權級3
!其中描述符索引1是CS段選擇符,可詳見下面gdt的定義
!jmpi 有反作用,會設置CS的值
    jmpi 0,8   

!下面是GDT的內容,3個段描述符,
!第一個不用,第2個是代碼段,第三個是數據段  
gdt:
!段描述符0,不用
    .word 0,0,0,0
!段描述符1,
!0x07FF十進制是2047,段限長,
!0x0000 段基地址,
!0x9A00 代碼段,可讀可執行
!0x00c0 段屬性顆粒度4k      
    .word 0x07FF,0x0000,0x9A00,0x00c0
!段描述符2,
!0x07FF十進制是2047,段限長,
!0x0000 段基地址,
!0x9200 數據段,可讀可寫
!0x00c0 段屬性顆粒度4k
    .word 0x07FF,0x0000,0x9200,0x00c0
!??
!下面的數據用於存放到IDTR和GDTR裏
!IDTR |---32位表基地址---|--16位表長度--|
!GDTR |---32位表基地址---|--16位表長度--|
!word. 16位長度,32位基地址
idt_48:
    .word 0,0,0
gdt_48:
    .word 0x7ff,0x7c00+gdt,0

!引導扇區的標誌
.org 510
    .word 0xAA55

$ cat head.s 

#  head.s contains the 32-bit startup code.
#  Two L3 task multitasking. The code of tasks are in kernel area, 
#  just like the Linux. The kernel code is located at 0x10000.
#
#  voidccc 20120921
#  編譯方法
#  as --32 -o head.o head.s
#  這是一個運行在保護模式下的AT&T彙編寫的多任務內核
#  代碼包括
#  1 初始化設置代碼
#  2 時鐘中斷代碼
#  3 系統調用中斷代碼 
#  4 任務a和任務b的代碼
#  在初始化完成以後程序移動到任務0開始執行,並在時鐘中斷控制下進行任務0和任務1之間的切換

#  書上代碼須要修改的地方
#  movl scr_loc, %bx => movlscr_loc, %ebx
#  movl $65, %al => movb $65, %al
#  movl $66, %al => movb $66, %al
#  align 2 => align 4
#  align 3 => align 8

SCRN_SEL = 0x18
TSS0_SEL = 0x20
LDT0_SEL = 0x28
TSS1_SEL = 0x30
LDT1_SEL = 0x38
                              #定時器初始值,即每隔10毫秒發送一次中斷請求。因爲8254芯片的時鐘輸入頻率爲1193180 Hz,因此芯片每隔1193190/100次計數,就會發出一個時鐘中斷請求信號,也就是每隔10毫秒左右(1秒的1/100)
LATCH = 11930

.text
                              # startup_32是特殊的標號,表示保護程序的開始位置
startup_32:

                              #首先加載DS SS ESP,全部段的線性基地址都是0,
                              #做爲三個段之一的CS此處不用從新設置,徹底是由於本次執行是從boot用長跳轉jmpi指令過來的,這個指令有反作用,會設置CS寄存器的值爲長跳轉的段寄存器
    movl $0x10, %eax
    mov %ax, %ds
    lss init_stack, %esp

                              #從新設置IDT和GDT表
    call setup_idt            #設置IDT,先把256箇中斷門都填默認處理過程的描述符
    call setup_gdt            #設置GDT
    movl $0x10, %eax          #在改變了GDT以後從新加載全部段寄存器
    mov %ax,%ds
    mov %ax,%es
    mov %ax,%fs
    mov %ax,%gs
    lss init_stack, %esp
                              #設置8253定時芯片。把計數器通道0設置成每隔10毫秒想中斷控制器發送一箇中斷請求信號
    movb $0x36, %al           #控制字:設置通道0工做方式在3,計數初值採用二進制。
    movl $0x43, %edx          #8253芯片控制字寄存器寫端口
    outb %al, %dx             
    movl $LATCH, %eax         #初始計數值設置爲LATCH, 100HZ
    movl $0x40, %edx          #通道0的端口
    outb %al, %dx             #分兩次把初始計數值寫入通道0
    movb %ah, %al
    outb %al, %dx

                              #在IDT表第8和第128(0x80)項處分別設置定製中斷門描述符和系統調用陷阱門描述符
    movl $0x00080000, %eax    #中斷程序屬內核,即eax高字是內核代碼段選擇符0x0008
    movw $timer_interrupt, %ax#設置定時中斷門描述符取定時中斷處理程序地址
    movw $0x8E00, %dx          #中斷門類型是14(屏蔽中斷)

    movl $0x08, %ecx          #開機時BIOS設置的時鐘中斷向量號8,這裏直接使用
    lea idt(,%ecx,8),%esi     #把IDT描述符0x80地址放入ESI
    movl %eax, (%esi)
    movl %edx,4(%esi)
    movw $system_interrupt, %ax
    movw $0xef00, %dx
    movl $0x80, %ecx
    lea idt(,%ecx,8),%esi
    movl %eax,(%esi)
    movl %edx,4(%esi)

                              #爲人工移動到任務0準備堆棧
    pushfl                    #復位標誌寄存器
    andl $0xffffbfff, (%esp)
    popfl
    movl $TSS0_SEL, %eax      #把任務0的TSS段選擇符加載到任務寄存器TR
    ltr %ax
    movl $LDT0_SEL, %eax      #把任務0的LDT段選擇符加載到局部描述符表寄存器LDTR
    lldt %ax                  #TR和DTR只須要人工加載一次,之後CPU會自動處理
    movl $0, current          #把當前任務號0保存在current變量中
    sti                       #如今開啓中斷,並在棧中營造中斷返回時的場景
    pushl $0x17               #把任務0當前局部控件數據段(堆棧段)選擇符入棧
    pushl $init_stack         #把堆棧指針入棧
    pushfl                    #把標誌寄存器值入棧
    pushl $0x0f               #把當前局部控件代碼段選擇符入棧
    pushl $task0              #把代碼指針入棧
    iret                      #執行中斷返回指令,從而切換到特權級3的任務0中執行
                              #如下是設置GDT和IDT中描述符的子程序
setup_gdt:
    lgdt lgdt_opcode          #使用6字節操做數lgdt_opcode設置GDT表位置和長度
    ret
                              #這段代碼暫時設置IDT表中全部256箇中斷門描述符都爲同一個默認值,均使用默認的中斷處理過程ignore_int,設置的具體方法是:首先在eax和edx寄存器對中分別設置好默認中斷門描述符的0-3字節和4-7字節的內容,而後利用寄存器對循環往IDT表中填充默認中斷門描述符內容。
setup_idt:
    lea ignore_int, %edx 
    movl $0x00080000, %eax    #選擇符爲0x0008
    movw %dx, %ax
    movw $0x8E00, %dx         #中斷門類型,特權級爲0
    lea idt, %edi
    mov $256, %ecx            #循環設置全部256個門描述符
rp_idt:
    movl %eax, (%edi)
    movl %edx, 4(%edi)
    addl $8, %edi
    dec %ecx
    jne rp_idt
    lidt lidt_opcode          #最後用6字節操做數加載IDTR寄存器
    ret
                              #顯示字符子程序
write_char:
    push %gs
    pushl %ebx
    mov $SCRN_SEL, %ebx
    mov %bx, %gs
    movl scr_loc, %ebx
    shl $1, %ebx
    movb %al, %gs:(%ebx)
    shr $1, %ebx
    incl %ebx
    cmpl $2000, %ebx
    jb 1f # ??
    movl $0, %ebx
1:
    movl %ebx, scr_loc
    popl %ebx
    pop %gs
    ret
                              # 如下是3箇中斷處理程序:默認中斷,定時中斷,系統調用中斷。
                              # ignore_int是默認的中斷處理程序,若系統產生了其餘中斷,則會在屏幕上顯示一個字符'C'
.align 4
ignore_int:
    push %ds
    pushl %eax
    movl $0x10, %eax
    mov %ax, %ds
    movl $67, %eax
    call write_char
    popl %eax
    pop %ds
    iret

                              #這是定時中斷處理程序,其中主要執行任務切換操做。
.align 4
timer_interrupt:
    push %ds
    pushl %eax
    movl $0x10, %eax
    mov %ax, %ds
    movb $0x20, %al
    outb %al, $0x20
    movl $1, %eax
    cmpl %eax, current
    je 1f
    movl %eax, current
    ljmp $TSS1_SEL, $0
    jmp 2f
1:
    movl $0, current
    ljmp $TSS0_SEL, $0
2:
    popl %eax
    pop %ds
    iret

                              #系統調用中斷 int0x80 處理程序,該示例只有一個顯示字符功能
.align 4
system_interrupt:
    push %ds
    pushl %edx
    pushl %ecx
    pushl %ebx
    pushl %eax
    movl $0x10, %edx
    mov %dx, %ds
    call write_char
    popl %eax
    popl %ebx
    popl %ecx
    popl %edx
    pop %ds
    iret
                              /*******************************************/
                              #數據區。沒有專門定義,是和代碼區混合編寫的。

current:
    .long 0                   #當前的任務號(0或者1)
scr_loc:
    .long 0                   #屏幕當前顯示位置,從左上到右下順序

.align 4                      #書上是 .align 2
lidt_opcode:
    .word 256*8-1             #16位表長,無法經過減法得到長度,是經過調用fill填充的
    .long idt                 #32位基地址
lgdt_opcode:
    .word (end_gdt-gdt)-1     #16位表長,能夠經過減法得到長度。
    .long gdt                 #32位基地址
.align 8                      #書上是 .align 3
idt:
    .fill 256,8,0             # 256個門描述符,每一個8字節,共佔用2KB
gdt:
                              #段描述符,可結合段描述符具體格式看
    .quad 0x0000000000000000  #第1描述符,不用,quad是4字節寬度
    .quad 0x00c09a00000007ff  #第2描述符,內核代碼段,基地址0 段限長7ff,2047字節,選擇符0x08 = 1:0:00
                              #   |    |  
                              #   +----+  高地址   方便查表的格式
                              #   | 00 |           | 00 c0 9a 00 |   
                              #   +----+           | 00 00 07 ff |
                              #   | c0 |
                              #   +----+  
                              #   | 9a |
                              #   +----+  
                              #   | 00 |
                              #   +----+  
                              #   | 00 |
                              #   +----+  
                              #   | 00 |
                              #   +----+  
                              #   | 07 |
                              #   +----+  低地址
                              #   | ff |  
                              #   +----+  
                              #   |    |  
    .quad 0x00c09200000007ff  #第3描述符,內核數據段,基地址0 只有TYPE段類型與第2描述符不同, 選擇符0x08 = 10:0:00
    .quad 0x00c0920b80000002  #第4描述符
    .word 0x0068,tss0,0xe900,0x0#第5描述符,TSS0段的描述符,基地址tss0,段限長104(0x68)
                              #   |        |  
                              #   +--------+  高地址   方便查表的格式
                              #   | 0x0000 |           | 00 00 e9 00 |      
                              #   +--------+           | tss0  00 68 |
                              #   | 0xe900 |
                              #   +--------+  
                              #   | tss0   |
                              #   +--------+  
                              #   | 0x0068 |  
                              #   +--------+  低地址
                              #   |        |  
    .word 0x0040,ldt0,0xe200,0x0#第6描述符,LDT0段的描述符,基地址ldt0,段限長0x40
    .word 0x0068,tss1,0xe900,0x0#第7描述符,TSS1段的描述符,基地址tss1,段限長0x68
    .word 0x0040,ldt1,0xe200,0x0#第8描述符,LDT1段的描述符,基地址ldt1,段限長0x40
end_gdt:                      #用來計算gdt表的長度
    .fill 128,4,0             #初始內核堆棧空間,後續給任務0當作內核數據段
init_stack:                   #剛進入保護模式時用於加載SS:ESP堆棧指針
    .long init_stack          #堆棧段偏移位置
    .word 0x10                #堆棧段起始地址,同數據段

                              #下面是任務0的LDT表段中的局部段描述符
.align 8                      #書上是 .align 3
ldt0:
    .quad 0x0000000000000000  #第1個描述符,不用
    .quad 0x00c0fa00000003ff  #第2個描述符,局部代碼段描述符,基地址是0,段限長3ff
    .quad 0x00c0f200000003ff  #第3個描述符,局部數據段描述符,基地址是0,段限長3ff
                              #下面是任務0的TSS段的內容
tss0:
    .long 0
    .long krn_stk0, 0x10      #
    .long 0,0,0,0,0           # esp1, ssl1, esp2, ss2, cr3
    .long 0,0,0,0,0           # eip, eflags, eax, ecx, edx  
    .long 0,0,0,0,0           # ebx, esp, ebp, esi, edi
    .long 0,0,0,0,0,0         # es, cs, ss, ds, fs, gs
    .long LDT0_SEL, 0x8000000 #
    .fill 128,4,0             #
krn_stk0:

                              #下面是任務1的LDT表段內容和TSS段內容
.align 8                      #書上是 .align 3
ldt1:
    .quad 0x0000000000000000  # 第1個描述符
    .quad 0x00c0fa00000003ff  # 第2個描述符
    .quad 0x00c0f200000003ff  # 第3個描述符

tss1:
    .long 0                   #同tss0
    .long krn_stk1, 0x10
    .long 0,0,0,0,0
    .long task1, 0x200        # eip eflags
    .long 0,0,0,0
    .long usr_stk1,0,0,0
    .long 0x17,0x0f,0x17,0x17,0x17,0x17
    .long LDT1_SEL, 0x8000000
    .fill 128,4,0             #任務1的內核棧空間
krn_stk1:

                              #下面是任務0和任務1的程序
task0:
    movl $0x17, %eax          #首先讓DS指向任務的局部數據段
    movw %ax, %ds             
    movb $65, %al             #把須要顯示的字符A放入AL寄存器中
                              #書上寫的是 movl $65 %al
    int $0x80                 #執行系統調用
    movl $0xfff, %ecx         #執行循環,起延時做用
1:  loop 1b
    jmp task0

task1:
    movl $0x17, %eax
    movw %ax, %ds
    movb $66, %al             #把須要顯示的字符B放入AL寄存器中
                              #書上寫的是 movl $66 %al
    int $0x80                 #系統調用
    movl $0xfff, %ecx         #延時一段時間,並跳轉到開始出繼續循環顯示
1:  loop 1b
    jmp task1

    .fill 128,4,0             #任務1的用戶棧空間
usr_stk1:

啓動

相關文章
相關標籤/搜索