文档章节

ubuntu下安装bochs并且运行linux0.00

wangxuwei
 wangxuwei
发布于 2017/01/10 21:11
字数 4644
阅读 55
收藏 0

ubuntu下安装bochs

安装gcc编译环境

sudo apt-get install build-essential

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

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

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

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

$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/local

修改Makefile(新版不需要)
LIBS =  
 -lz -lrt -lm -lpthread 

$make
$cp bochs bochsdbg
$sudo make install

安装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:

启动

© 著作权归作者所有

共有 人打赏支持
wangxuwei
粉丝 25
博文 332
码字总数 115454
作品 0
杭州
其他
私信 提问
ubuntu中安装bochs后,设置好配置文件后运行bochs,出现一个全黑的窗口

按照《一个操作系统的实现》里第二章的步骤操作,bochsrc文件配置好了,运行bochs时弹出的窗口只是一片黑,没有bochs正常运行的界面,只是一个黑色的界面!这是为什么!! 我系统win7 64位,...

infouryears
2012/09/01
2.1K
1
Ubuntu下bochs的安装配置

目前市面上流行的全虚拟化PC仿真软件系统主要有三种:VMware公司的VMware Workstation软件、Microsoft公司的Virtual PC以及开放源代码的Bochs。这3种软件都可以虚拟或仿真Intel x86硬件环境,...

xwisen
2014/07/21
0
0
在Linux上编译安装Bochs和QEMU的方法

Bochs和QEMU都是开源的模拟器软件(也可称为虚拟机软件),通常用来运行和调试操作系统。 准备工作: 1、一台安装有Ubuntu系统(本文用的是64位的16.04.3版本)的计算机或虚拟机 2、必须安装...

ryanliue
2017/10/30
0
0
Ubuntu 12.10安装Bochs 2.6, 调试linux-0.11内核

http://blog.csdn.net/sinzou1/article/details/5903968 Linux(ubuntu)安装bochs http://wenku.baidu.com/view/f968e23b0912a21614792914.html ubuntu下安装bochs http://www.linuxidc.com/L......

xwisen
2014/07/22
0
0
关于 80x86保护模式和编程,有看过《linux完全剖析》的么?

最近是在研读赵炯的《linux完全剖析》,学习操作系统原理。这两天已经进行到进程部分,为了更透彻地理解其原理,自己照着书上的linux0.00源 码写了一个单进程的模型。前面还好,当由特权级0...

Fuz
2012/06/04
380
1

没有更多内容

加载失败,请刷新页面

加载更多

码云项目100,水一发

简单回顾一下: 早期构想最多的,是希望能将PHP一些类和编码分区做得更细,所以很多尝试。但不得不说,PHP的功能过于单一,是的,也许写C/C++扩展,可以解决问题,那我为什么不用C#或者Golan...

曾建凯
今天
3
0
Spring应用学习——AOP

1. AOP 1. AOP:即面向切面编程,采用横向抽取机制,取代了传统的继承体系的重复代码问题,如下图所示,性能监控、日志记录等代码围绕业务逻辑代码,而这部分代码是一个高度重复的代码,也就...

江左煤郎
今天
4
0
eclipse的版本

Eclipse各版本代号一览表 Eclipse的设计思想是:一切皆插件。Eclipse核心很小,其它所有功能都以插件的形式附加于Eclipse核心之上。 Eclipse基本内核包括:图形API(SWT/Jface),Java开发环...

mdoo
今天
3
0
SpringBoot源码:启动过程分析(一)

本文主要分析 SpringBoot 的启动过程。 SpringBoot的版本为:2.1.0 release,最新版本。 一.时序图 还是老套路,先把分析过程的时序图摆出来:时序图-SpringBoot2.10启动分析 二.源码分析 首...

Jacktanger
今天
6
0
小白带你认识netty(二)之netty服务端启动(上)

上一章 中的标准netty启动代码中,ServerBootstrap到底是如何启动的呢?这一章我们来瞅下。 server.group(bossGroup, workGroup);server.channel(NioServerSocketChannel.class).optio...

天空小小
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部