DD系统构建-MBR(5)加载loader文件

在上一章节,我们验证了在mbr超过512字节时,如何能正确将超出512字节内容加载到内存处,并能正确运行;理解了这点,对于我们下面的加载loader大有帮助。

本章节我们来尝试mbr加载loader.bin文件,并能跳转到loader.bin处执行。

首先,我们得先有个能生成loader.bin的文件才行,我们可以写一个简单的Loader.asm,代码如下:

loader.asm

%include "base_phy.inc"    

section code align=16 vstart=0
jmp start
%include "filesystem.inc"
;;;;;;;;;;;栈区空间预留;;;;;;;
stack_rsv:
		times 1024 db 0
stack_top:

;;;;;;;;;;;数据区预留;;;;;;;;
loaderMsg     db  "loader is running...", 0ah,0dh;
loaderMsgLen  equ $-loaderMsg

;;;;;;;;;;;代码区;;;;;;;;
start:
    mov ax, cs
    mov ds, ax
    mov es, ax
	mov ss, ax
    
	;栈顶赋值
    mov sp, stack_top
	
    ;显示loader运行信息
    mov	cx, loaderMsgLen ; CX = 串长度
    push cx
    mov	cx, loaderMsg	
    push cx
    call showString
    pop cx
    pop cx
	
	jmp $
	
;showString(字符串地址,字符串长度)
;在当前当前光标处显示字符串信息
;字符串地址: bp+4
;字符串长度: bp+6
showString:
    push bp
    mov bp, sp

    pusha

    mov ax, 0x0300
    mov bx, 0
    int 0x10

    mov	cx, [bp+6] ; CX = 串长度
    mov	bp, [bp+4]	
    mov	ax, 0x1301		; AH = 0x13,  AL = 0x1
    mov	bx, 0x7			; 页号为0(BH = 0) 黑底白字(BL = 0x7)
    int	0x10			; int 0x10

    popa
    pop bp
    
    ret
本章用到的loader.asm代码就这么多,功能也很简单,就是打印个loader is running..., 当前如果能打印出这句话,就说明我们的loader成功获取了cpu执行控制权。

它的效果会如下,我们提前透露下:




为了能运行这个loader.bin,首先要把loader.asm编译成loader.bin, 然后把它磁盘中;在启动bochs后,在mbr里面要能找到这个loader.bin占用的扇区,并能把它的内容加载 到内存指定位置处。

简单来说就是:(1)编译loader.asm -> (2)将loader.bin写入磁盘 -> (3)启动bochs -> (4)mbr寻找并加载Loader.bin ->(5) 控制权给Loader.bin

第一步与第二步其实不难,我们可以用nasm 及在前面说到的文件系统工具(http://blog.csdn.net/b06030927/article/details/73050529)Install_file工具即可。

其实我们的mbr要做的工作主要是:找到Loader.bin并加载它,然后交出控制权。

如何找到loader.bin? 这依赖这个Loader.bin是如何 写入磁盘的。我们使用install_file写入时,这实际是用我们自己的文件系统在组织这个文件的存放。它会占用扇区,Inode相关的信息。我们只要找到它对应的inode,就能找 出它所有的扇区信息。所不同的是我们要用nasm来实现

代码如下:

boot.asm

%include "base_phy.inc"

section mbr align=16 vstart=MACRO_BOOT_ADDR 
jmp start

;数据区
bootmsg:      db  "MBR running..", 0ah,0dh;
bootmsglen:   equ $-bootmsg

mbr_left_len dw mbr_end-loader_begin

;代码区
start:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax

mov sp, MACRO_BOOT_ADDR

;清除屏幕
call clearScreen

;显示mbr加载信息
mov	cx, bootmsglen ; CX = 串长度
push cx
mov	cx, bootmsg	
push cx
call showString
pop cx
pop cx

;计算mbr剩余内容占用的扇区数目,不足一个扇区的按照一个扇区计算
mov dx, 0
mov ax, [mbr_left_len]
add ax, 511
mov bx, 512                      ;512字节每扇区
div bx
;MBR只有当前这一个扇区,直接加载loader
cmp ax, 0
jz load_loader

;依次压入起始内存地址,扇区数目,扇区起始号
mov ecx, MACRO_BOOT_LEFT_START_ADDR
push ecx
push ax
mov si, MACRO_BOOT_LEFT_START_SECTOR ;mbr剩余内容的起始扇区
push si
call getDataFromSectors
pop si
pop ax
pop ecx

jmp load_loader

;clearScreen
;清除当前屏所有字符,同时光标设置为起始0,0处
clearScreen:
    pusha
    
    mov ax, 0x0600               ; AH = 6,  AL = 0
    mov bx, 0x0700               ; 黑底白字
    mov cx, 0                   ; 左上角: (0, 0)
    mov dx, 0x184f              ; 右下角: (80, 50)
    int 0x10                    ; int 0x10

    mov ax, 0x0200
    mov bx, 0
    mov dx, 0
    int 0x10

    popa
    
    ret

;showString(字符串地址,字符串长度)
;在当前当前光标处显示字符串信息
;字符串地址: bp+4
;字符串长度: bp+6
showString:
    push bp
    mov bp, sp

    pusha

    mov ax, 0x0300
    mov bx, 0
    int 0x10

    mov	cx, [bp+6] ; CX = 串长度
    mov	bp, [bp+4]	
    mov	ax, 0x1301		; AH = 0x13,  AL = 0x1
    mov	bx, 0x7			; 页号为0(BH = 0) 黑底白字(BL = 0x7)
    int	0x10			; int 0x10

    popa
    pop bp
    
    ret
    
;getDataFromSectors(起始扇区号,扇区数目,起始内存地址)
;从指定扇区位置处连续加载指定数目个扇区到指定的内存起始位置处
;起始扇区号;bp+4 2字节
;扇区数目;  bp+6 2字节
;起始内存地址: bp+8 4字节
getDataFromSectors:
    push bp
    mov bp, sp

    pusha
    push es

    ;加载的内存起始地址
    mov ecx, [bp+8]
    ;要读取的扇区数目
    mov ax, [bp+6]
    ;起始扇区号
    mov si, [bp+4]

    ;剩余内容加载 到es:di起始处
	push ecx
    shr ecx, 4
    mov es, cx
	pop ecx
	and ecx, 0x000f
	mov di, cx

    mov dx,0x1f2
    out dx,al                       ;读取的扇区数

    inc dx                          ;0x1f3
    mov ax,si
    out dx,al                       ;LBA地址7~0

    inc dx                          ;0x1f4
    mov al,ah
    out dx,al                       ;LBA地址15~8

    xor ax, ax

    inc dx                          ;0x1f5
    out dx,al                       ;LBA地址23~16

    inc dx                          ;0x1f6
    mov al,0xe0                     ;LBA28模式,主盘
    out dx,al

    inc dx                          ;0x1f7
    mov al,0x20                     ;读命令
    out dx,al

    .waits:
        in al,dx
        and al,0x88
        cmp al,0x08
        jnz .waits                      ;不忙,且硬盘已准备好数据传输 

    ;计算要循环读取的字节数目,由于一次读取是2个字节,因此总字节除以2
    mov ax, [bp+6]    
    mov bx, 512
    mul bx
    
    mov bx, 2
    div bx
    mov cx, ax

    mov dx,0x1f0
    .readw:
        in ax,dx
        mov [es:di],ax
        add di, 2
        loop .readw

    pop es
    popa
    pop bp
    
    ret

times 510-($-$$) db 0
db 0x55, 0xaa

;剩余内容
loader_begin:
loadermsg:      db  "Try to search loader and load it..", 0ah,0dh;
loadermsglen:   equ $-loadermsg

loadername      db  "loader.bin",0h
loadernamelen:  equ $-loadername

loadernotfoundmsg:       db  "Failed to find the loader.bin, quit..", 0ah,0dh;
loadernotfoundmsglen:    equ $-loadernotfoundmsg

;临时数据区,用来保存读取一个扇区内容
tempbuffer: times 512 db 0
tempinodeinfobuffer: times 64 db 0
tempoutresult: times 2 db 0

%include "filesystem.inc"

load_loader:
    ;显示mbr加载信息
    mov	cx, loadermsglen ; CX = 串长度
    push cx
    mov	cx, loadermsg	
    push cx
    call showString
    pop cx
    pop cx
	
	;获取系统块区
	mov ebx, tempbuffer
	push ebx
	call getSystemBlockData
	pop ebx
	
	cmp dword [tempbuffer+MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_USEDINODENUM], 0
	jz loadernotfound
	
	;2.读取inodebitmap位图,按照位图再读取对应inodeinfo信息,检查是否是Loader.bin
	mov ebx, tempbuffer
	push ebx
    call getInodeBitMapData
	pop ebx
	
	mov cx, MACRO_DDFS_FILESYSTEM_INODE_NUM
	mov ax, 0
check_bit_is_set:	
	mov ebx, tempoutresult
	push ebx
	mov ebx, tempbuffer
	push ebx
	mov bx, ax
	push bx
    call checkBitIsSet
	pop bx
	pop ebx
	pop ebx
	cmp word [tempoutresult], 1
	jz  getinodeinfo
search_next_bit:
	inc ax
	loop check_bit_is_set
	jmp loadernotfound
	
getinodeinfo:
    ;根据inode索引(保存在dx中)计算它对应的Inodeinfo所有的起始扇区及偏移位置
	mov ebx, tempinodeinfobuffer
	push ebx
	push ax
	call getInodeInfoByInodeIndex
	pop ax
	pop ebx
	
	mov ebx, tempoutresult
	push ebx
	mov bx, loadernamelen
	push bx
	mov ebx, loadername
	push ebx
    mov ebx, tempinodeinfobuffer
	push ebx
    call checkFileNameIsSame
	pop ebx
	pop ebx
	pop bx
	pop ebx
	cmp word [tempoutresult], 1
	jnz search_next_bit
		
file_is_same:
	;获取文件起始扇区
	mov bx, tempinodeinfobuffer
	add bx, MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESTARTSECTOR
	mov ax, [bx] ;起始扇区号
	
    mov ebx, MACRO_LOADER_ADDR
load_all_loader:
	push ebx
	mov cx, 1
	push cx
	mov cx, ax
	push cx
	call getDataFromSectors
	pop cx
	pop cx
	pop ebx 
	
	;计算下一个扇区
	mov ecx, tempbuffer
	push ecx
	mov cx, ax
	push cx
	call getFileSectorListBySector
	pop cx
	pop ecx
	
    mov cx, [tempbuffer+MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_ISNEXTVALID]
	cmp cx, 1
	jnz jmp_loader
get_next_sector:	
	mov ax, [tempbuffer+MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_NEXTSECTOR]
	add ebx, 512
	jmp load_all_loader

jmp_loader:
	mov ebx, MACRO_LOADER_ADDR
	and ebx, 0xf
    mov ax, bx	
	mov ebx, MACRO_LOADER_ADDR
	shr ebx, 4
	
	mov [tempbuffer], ax
	mov [tempbuffer+2], bx
	jmp far [tempbuffer]
	
loadernotfound:
	mov	cx, loadernotfoundmsglen ; CX = 串长度
    push cx
    mov	cx, loadernotfoundmsg	
    push cx
    call showString
    pop cx
    pop cx

	jmp $
mbr_end:


上面的loader.asm 与boot.asm都include了一个filesystem.inc, 这是我们新增加的一个文件,用来把文件系统操作的相关的函数 封装在里面,方便我们进行调用。

filesystem.inc如下

filesystem.inc

;文件系统相关的宏定义
MACRO_DDFS_SYSTEMBLOCK_START_SECTOR_NO  EQU 1
MACRO_DDFS_SYSTEMBLOCK_SECTOR_NUM EQU 1

MACRO_DDFS_SECTORBITMAP_START_SECTOR_NO  EQU 2
MACRO_DDFS_SECTORBITMAP_SECTOR_NUM EQU 1

MACRO_DDFS_INODEBITMAP_START_SECTOR_NO  EQU 3
MACRO_DDFS_INODEBITMAP_SECTOR_NUM EQU 1

MACRO_DDFS_INODEINFO_START_SECTOR_NO  EQU 4
MACRO_DDFS_INODEINFO_SECTOR_NUM EQU 512

MACRO_DDFS_FILESECTORLIST_START_SECTOR_NO  EQU 516
MACRO_DDFS_FILESECTORLIST_SECTOR_NUM EQU 32

MACRO_DDFS_FILEDATA_START_SECTOR_NO  EQU 548
MACRO_DDFS_FILEDATA_SECTOR_NUM EQU 3548

MACRO_DDFS_FILESYSTEM_SIZE_SYSTEMBLOCK EQU 16
MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_TOTALSECTORNUM EQU 0
MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_USEDSECTORNUM EQU 4
MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_TOTALINODENUM EQU 8
MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_USEDINODENUM EQU 12


MACRO_DDFS_FILESYSTEM_SIZE_INODEINFO   EQU 64
MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILENAME EQU 0
MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESIZE EQU 32
MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESECTORNUM EQU 36
MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESTARTSECTOR EQU 40

MACRO_DDFS_FILESYSTEM_SIZE_FILESECTORLIST  EQU 8
MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_ISNEXTVALID EQU 0
MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_NEXTSECTOR EQU 4


MACRO_DDFS_FILESYSTEM_INODE_NUM  EQU 4096


globalSectorSpace: times 512 db 0

;-------------------------------------------------------------
;函数名:getDiskDataFromSectors(起始扇区号, 扇区数目, 起始内存地址)
;函数说明:从指定起始扇区处连续加载指定扇区数目的数据到指定的内存起始位置处
;函数参数:
;    参数说明      参数位置 参数大小
;    起始扇区号,  bp+4     2字节
;    扇区数目,    bp+6     2字节
;    起始内存地址: bp+8     4字节
;返回值:
;    无
;-------------------------------------------------------------
getDiskDataFromSectors:
    push bp
    mov bp, sp

    pushad
    push es

    ;加载的内存起始地址
    mov ecx, [bp+8]
    ;要读取的扇区数目
    mov ax, [bp+6]
    ;起始扇区号
    mov si, [bp+4]

    ;剩余内容加载 到es:di起始处
	push ecx
    shr ecx, 4
    mov es, cx
	pop ecx
	and ecx, 0x000f
	mov di, cx

    mov dx,0x1f2
    out dx,al                       ;读取的扇区数

    inc dx                          ;0x1f3
    mov ax,si
    out dx,al                       ;LBA地址7~0

    inc dx                          ;0x1f4
    mov al,ah
    out dx,al                       ;LBA地址15~8

    xor ax, ax

    inc dx                          ;0x1f5
    out dx,al                       ;LBA地址23~16

    inc dx                          ;0x1f6
    mov al,0xe0                     ;LBA28模式,主盘
    out dx,al

    inc dx                          ;0x1f7
    mov al,0x20                     ;读命令
    out dx,al

    .waits:
        in al,dx
        and al,0x88
        cmp al,0x08
        jnz .waits                      ;不忙,且硬盘已准备好数据传输 

    ;计算要循环读取的字节数目,由于一次读取是2个字节,因此总字节除以2
    mov ax, [bp+6]    
    mov bx, 512
    mul bx
    
    mov bx, 2
    div bx
    mov cx, ax

    mov dx,0x1f0
    .readw:
        in ax,dx
        mov [es:di],ax
        add di, 2
        loop .readw

    pop es
    popad
	
    pop bp
    
    ret

;-------------------------------------------------------------
;函数名:getSystemBlockData(buf)
;函数说明:获取文件系统块,保存buf中
;函数参数:
;    参数说明      参数位置 参数大小
;    buf           bp+4     4字节
;返回值:
;    无
;补充说明:
;-------------------------------------------------------------
getSystemBlockData:
    push bp
    mov bp, sp
	
    pushad
	
	mov eax, [bp+4] 
	
	push eax
	mov ax, MACRO_DDFS_SYSTEMBLOCK_SECTOR_NUM
	push ax
	mov ax, MACRO_DDFS_SYSTEMBLOCK_START_SECTOR_NO
	push ax
	call getDiskDataFromSectors
	pop ax
	pop ax
	pop eax
	
	popad
    
	pop bp
	ret
	
;-------------------------------------------------------------
;函数名:getInodeBitMapData(buf)
;函数说明:获取inodebitmap,保存到buf中
;函数参数:
;    参数说明      参数位置 参数大小
;    buf           bp+4     4字节
;返回值:
;    无
;补充说明:
;-------------------------------------------------------------
getInodeBitMapData:
    push bp
    mov bp, sp
	
    pushad

	mov eax, [bp+4] 

	push eax
	mov ax, MACRO_DDFS_INODEBITMAP_SECTOR_NUM
	push ax
	mov ax, MACRO_DDFS_INODEBITMAP_START_SECTOR_NO
	push ax
	call getDiskDataFromSectors
	pop ax
	pop ax
	pop eax
	
	popad

	pop bp
	ret
	
;-------------------------------------------------------------
;函数名:getInodeInfoByInodeIndex(inodeindex, buf)
;函数说明:通过inode索引获取对应的inodeinfo
;函数参数:
;    参数说明      参数位置 参数大小
;    inodeindex    bp+4     2
;    buf           bp+6     4字节
;返回值:
;    eax: 0:未使用 1:已经使用
;补充说明:
;-------------------------------------------------------------
getInodeInfoByInodeIndex:
    push bp
    mov bp, sp
	
    pushad

	mov ax, [bp+4] 
	xor edx, edx
	mov bx, MACRO_DDFS_FILESYSTEM_SIZE_INODEINFO
	mul bx
    ;除以512后,ax保存扇区偏移,dx保存扇区内偏移
	mov bx, 512
	div bx
	add ax, MACRO_DDFS_INODEINFO_START_SECTOR_NO

    mov ebx, globalSectorSpace
	push ebx
	mov bx, 1
	push bx
	mov bx, ax
	push bx
	call getDiskDataFromSectors
	pop bx
	pop bx
	pop ebx
	
	;将64字节内容拷贝到用户区
	push es
	push ds

	mov ebx, globalSectorSpace
	add ebx, edx
	push ebx
	shr ebx, 4
	mov ds, bx
	pop ebx
	and ebx, 0xf
	mov si, bx
	
	mov ebx, [bp+6]
	push ebx
	shr ebx, 4
	mov es, bx
	pop ebx
	and ebx, 0xf
	mov di, bx
	
	mov cx, MACRO_DDFS_FILESYSTEM_SIZE_INODEINFO
	cld
	rep movsb
	
	pop ds
	pop es
	
	popad

	pop bp
	ret

;-------------------------------------------------------------
;函数名:getFileSectorListBySector(sector, buf)
;函数说明:通过Secto索引获取对应的filesectorlist信息
;函数参数:
;    参数说明      参数位置 参数大小
;    sector        bp+4     2
;    buf           bp+6     4字节
;返回值:
;    eax: 0:未使用 1:已经使用
;补充说明:
;-------------------------------------------------------------
getFileSectorListBySector:
    push bp
    mov bp, sp
	
    pushad
	
	mov ax, [bp+4]
	xor edx,edx
    mov bx, MACRO_DDFS_FILESYSTEM_SIZE_FILESECTORLIST
	mul bx
	mov bx,512
	div bx
	
	mov ebx, globalSectorSpace
	push ebx
	mov bx, 1
	push bx
	mov bx, MACRO_DDFS_FILESECTORLIST_START_SECTOR_NO
	add bx, ax
	push bx
	call getDiskDataFromSectors
	pop bx
	pop bx
	pop ebx
	
	;将8字节内容拷贝到用户区
	push es
	push ds

	mov ebx, globalSectorSpace
	add ebx, edx
	push ebx
	shr ebx, 4
	mov ds, bx
	pop ebx
	and ebx, 0xf
	mov si, bx
	
	mov ebx, [bp+6]
	push ebx
	shr ebx, 4
	mov es, bx
	pop ebx
	and ebx, 0xf
	mov di, bx
	
	mov cx, MACRO_DDFS_FILESYSTEM_SIZE_FILESECTORLIST
	cld
	rep movsb
	
	pop ds
	pop es	
    
    popad

    pop bp
    ret

;-------------------------------------------------------------
;函数名:checkFileNameIsSame(dstFileName, srcFileName, FileLen, outBuf)
;函数说明:比较指定长度的源目的文件名是否相同
;函数参数:
;    参数说明      参数位置 参数大小
;    dstFileName   bp+4     4字节
;    srcFileName   bp+8     4字节
;    dstFileName   bp+12    2字节
;    outBuf        bp+14    4字节
;返回值:
;    outBuf: 0:不相同 1:相同
;补充说明:
;-------------------------------------------------------------
checkFileNameIsSame:
    push bp
    mov bp, sp
	
    pushad
	
	push ds
	push es
	
	mov ebx, [bp+4]
	push ebx
	shr ebx, 4
	mov ds, bx
	pop ebx
	and ebx, 0xf
	mov si, bx
	
	mov ebx, [bp+8]
	push ebx
	shr ebx, 4
	mov es, bx
	pop ebx
	and ebx, 0xf
	mov di, bx
	
	mov cx, [bp+12]
	cld
	repz cmpsb
	
	cmp cx, 0
	jz file_name_same
	
	mov ebx, [bp+14]
	push ebx
	shr ebx, 4
	mov ds, bx
	pop ebx
	and ebx, 0xf
	mov si, bx
	mov word [si], 0
	
	pop es
	pop ds

    popad
	
	pop bp
	ret

file_name_same:	
	mov ebx, [bp+14]
	push ebx
	shr ebx, 4
	mov ds, bx
	pop ebx
	and ebx, 0xf
	mov si, bx
	mov word [si], 1
	
	pop es
	pop ds

    popad
	
	pop bp
	ret

	;-------------------------------------------------------------
;函数名:checkFileNameIsSame(bitIndex, bitBuffer, outBuf)
;函数说明:比较指定长度的源目的文件名是否相同
;函数参数:
;    参数说明      参数位置 参数大小
;    bitIndex      bp+4     2字节
;    bitBuffer     bp+6     4字节
;    outBuf        bp+10    4字节
;返回值:
;    outBuf: 0:不相同 1:相同
;补充说明:
;-------------------------------------------------------------
checkBitIsSet:
    push bp
    mov bp, sp
	
    pushad
	xor eax, eax
	
	mov ax, [bp+4]
	mov ebx, [bp+6]
	mov ecx, [bp+10]
	
	push ebx
	xor dx, dx
	mov bx, 8
	div bx
	pop ebx
	
	add ebx, eax
	
	push ds
	
	push ebx
	shr ebx, 4
	mov ds, bx
	pop ebx
	and ebx, 0xf
	mov si, bx
	
	bt [si], dx
	jc bit_is_set
	
	push ecx
	shr ecx, 4
	mov ds, cx
	pop ecx
	and ecx, 0xf
	mov si, cx
	
	mov word [si], 0

	pop ds
	
    popad
	
	pop bp
	ret


bit_is_set:
    push ecx
	shr ecx, 4
	mov ds, cx
	pop ecx
	and ecx, 0xf
	mov si, cx
	
	mov word [si], 1

	pop ds
	
    popad
	
	pop bp
	ret


base_phy.inc文件基本没有修改,沿用以前的,从这里面我们能看到Loader会被加载到0x10000内存处(我们的mbr是加载到0x7c00处)

base_phy,inc

MACRO_BOOT_ADDR equ   0x7c00
MACRO_BOOT_LEFT_START_SECTOR equ 4096
MACRO_BOOT_LEFT_START_ADDR   equ MACRO_BOOT_ADDR+512

MACRO_LOADER_ADDR equ 0x10000 

MACRO_KERNEL_ADDR  equ 0x500000

MACRO_GDT_ADDR  equ   0x8000  

MACRO_PAGEDIR_ADDR equ 0x20000 
MACRO_PAGETBL_ADDR equ 0x21000 

现在我们涉及到的代码者在上面了,对于 Loader.asm还要新增加它对应的makefile及适配build_all.sh

loader.asm的makeFile

.PHONY : all clean loader loader_clean

all : loader ../include/base_phy.inc ../include/filesystem.inc
loader : loader.asm
	$(ASM)  $(ASMFLAG) $< -o $(RELEASE_LOADER_NAME)
	
clean : loader_clean
loader_clean :
	rm $(RELEASE_LOADER_NAME)

在build_all.sh中增加对Loader的适配(bulild_loader)

#!/bin/sh
#对变量赋值: 
source ./env.sh
function bulild_root()
{
    if [ ! -d $RELEASE_BOOT_DIR ]
    then 
        mkdir -p $RELEASE_BOOT_DIR
    else
        rm -rf $RELEASE_BOOT_DIR/*
    fi
    
	make -C boot
    
	if [ ! -f $RELEASE_BOOT_NAME ]
	then
        echo "Error in build root"
        return 1		
	fi
	
	dd if=/dev/zero of=$IMG_NAME bs=512 count=1 conv=notrunc
    dd if=$RELEASE_BOOT_NAME of=$IMG_NAME bs=512 count=1 conv=notrunc
    dd if=$RELEASE_BOOT_NAME of=$IMG_NAME bs=1 count=$((`du -b $RELEASE_BOOT_NAME | cut -f 1` - 512)) conv=notrunc skip=512 seek=2097152
	return 0
}

function bulild_loader()
{
    if [ ! -d $RELEASE_LOADER_DIR ]
    then 
        mkdir -p $RELEASE_LOADER_DIR
    else
        rm -rf $RELEASE_LOADER_DIR/*
    fi
	
    make -C loader
	
	if [ ! -f $RELEASE_LOADER_NAME ]
	then
        echo "Error in build loader"
        return 1		
	fi
	
	#loaderfilesize=`ls -l $RELEASE_LOADER_NAME | cut -d " " -f 5`
	#dd if=/dev/zero of=$IMG_NAME bs=1 count=$loaderfilesize seek=512 conv=notrunc
    #dd if=$RELEASE_LOADER_NAME of=$IMG_NAME bs=1 count=$loaderfilesize seek=512 conv=notrunc
	$RELEASE_TOOLS_INSTALL_FILE $IMG_NAME $RELEASE_LOADER_NAME 
	return 0
}

function bulild_kernel()
{
    if [ ! -d $RELEASE_KERNEL_DIR ]
    then 
        mkdir -p $RELEASE_KERNEL_DIR
    else
        rm -rf $RELEASE_KERNEL_DIR/*
    fi
	
    make -C kernel
	
	if [ ! -f $RELEASE_KERNEL_NAME ]
	then
        echo "Error in build kernel"
        return 1		
	fi
	
	kernelfilesize=`ls -l $RELEASE_KERNEL_NAME | cut -d " " -f 5`
	dd if=/dev/zero of=$IMG_NAME bs=1 count=$kernelfilesize seek=51200 conv=notrunc
    dd if=$RELEASE_KERNEL_NAME of=$IMG_NAME bs=1 count=$kernelfilesize seek=51200 conv=notrunc
	return 0
}

if [ -z $1 ] || [ $1 == all ]
then
    echo build all
	bulild_root
	bulild_loader
	bulild_kernel
elif [ $1 == boot ]
then
    echo build boot
	bulild_root
elif [ $1 == loader ]
then
    echo build loader
	bulild_loader
elif [ $1 == kernel ]
then
    echo build kernel
	bulild_kernel
else
    echo "./build.sh [ boot | loader | kernel | all]"
	exit 0
fi


env.sh里面增加Loader路径

#!/bin/sh
#对变量赋值: 
export ASM=nasm
export ASMFLAG="-I `pwd`/include/"

export CC=gcc

export RELEASE=`pwd`/release
export IMG_NAME=`pwd`/os.img

#boot
export RELEASE_BOOT_DIR=`pwd`/release/boot
export RELEASE_BOOT_NAME=`pwd`/release/boot/boot.bin

#loader
export RELEASE_LOADER_DIR=`pwd`/release/loader
export RELEASE_LOADER_NAME=`pwd`/release/loader/loader.bin

#kernel
export RELEASE_KERNEL_DIR=`pwd`/release/kernel
export RELEASE_KERNEL_NAME=`pwd`/release/kernel/kernel.bin

#tools
export RELEASE_TOOLS_DIR=`pwd`/release/tools
export RELEASE_TOOLS_READDDFS=`pwd`/release/tools/readddfs
export RELEASE_TOOLS_MKDDFS=`pwd`/release/tools/mkddfs
export RELEASE_TOOLS_INSTALL_FILE=`pwd`/release/tools/install_file


这样我们修改的文件如下:


pengsheng@pengsheng-VirtualBox:/media/sf_E_DRIVE/ubuntu_backup/BRANCHS_OS/DD_OS$ tree
.
├── app
├── bochsrc
── boot
│   ├── boot.asm
│   └── Makefile
├── build_all.sh
├── env.sh
├── include
│   ├── base_phy.inc
│   └── filesystem.inc

├── kernel
│   ├── kernel.asm
│   └── Makefile
── loader
│   ├── loader.asm
│   └── Makefile

├── os.img
├── release
│   ├── boot
│   │   └── boot.bin
│   ├── kernel
│   │   └── kernel.bin
│   ├── loader
│   │   └── loader.bin
│   └── tools
│       ├── install_file
│       ├── mkddfs
│       └── readddfs
├── test.img
├── tools
│   ├── ddfs.c
│   ├── ddfs.h
│   ├── install_file.c
│   ├── Makefile
│   ├── mkddfs.c
│   └── readddfs.c
└── 设计相关
    ├── 临时设计.xls
    └── 流程图.vsd


12 directories, 27 files
pengsheng@pengsheng-VirtualBox:/media/sf_E_DRIVE/ubuntu_backup/BRANCHS_OS/DD_OS$ 




下一章节我们对改装后的boot.asm进行详细讲解。有兴趣的可以尝试下编译。

build_all.sh boot

build_all.sh loader

bochs


ps提供下bochsrc文件。

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

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

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

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

# hard disk
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
# !! Remember to change these if the hd img is changed:
#    1. include/sys/config.h::MINOR_BOOT
#    2. boot/include/load.inc::ROOT_BASE
#    3. Makefile::HD
#    4. commands/Makefile::HD
ata0-master: type=disk, path="os.img", mode=flat, cylinders=40, heads=16, spt=63
#ata0-master: type=disk, path="20m.img", mode=flat, cylinders=40, heads=16, spt=63
# choose the boot disk.
boot: disk

# 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=/usr/share/bochs/keymaps/x11-pc-us.map


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值