我写了两个文件。一个文件是 bootsect.asm,另一个是 setup.asm。
bootsect 的作用是把 setup 加载到内存地址 0x00500 处,显示一点提示信息,然
后跳转到 setup 中执行。在 setup 中,在屏幕第 10 行 39 列显示一个黑底红
字的字母“S”。
刚才说过 bootsect 显示一些提示信息,这些提示信息是:
Loading loader.
load loader ok.
Jumping to setup.
因为我没有写换行,所以都在同一行显示。
现在问题是,我没有发现红色的字符“L”。
下面附上代码,我知道肯定是什么地方出错了。不过我不知道在哪里错了,请大
家帮忙看看。谢谢。
Code:
bootsect.asm
------------------------------------------------------------
;; Program: bootsect.asm
;; Purpose: This is a boot sector.
;; org 0x7c00
jmp start
nop ; 真的需要这个延时吗?
loading_msg: db "Loading loader.", 0
loader_fail_msg: db "loading loader failed.", 0
loading_ok_msg: db "load loader ok.", 0
msg_jumping: db "Jumping to setup.", 0
start:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov ax, 0xb800
mov gs, ax ; Mono text video buffer
mov sp, 0x9fc0
load_setup:
mov cx, loading_msg
mov di, (80 * 20 + 0) * 2
call disp_str
;; int 0x13
;; ah=2, al=要读的扇区数
;; ch=柱面号(磁道)号, cl=起始扇区号
;; dh=磁头号 dl=驱动器号(0 表示 A 盘)
;; es:bx --> 数据缓冲区
mov ax, 0x0
mov es, ax ; loader 的段基址是 0x0000
mov bx, 0x0500 ; loader 的偏移地址是 0x0500
mov ah, 2
mov al, 5
mov ch, 0
mov cl, 1
mov dh, 0
mov dl, 0
int 0x13
jnc load_ok ; 当 CF=0 时,表明没有错误
load_failed:
push cx
mov cx, loader_fail_msg
call disp_str
pop cx
jmp $
load_ok:
push cx
mov cx, loading_ok_msg
call disp_str
pop cx
mov cx, msg_jumping
call disp_str
pop cx
jmp 0x0050:0 ; 跳转到 setup.asm。段基址:段内偏移
;; disp_str: 将地址为 si 的字符串写入显存
disp_str:
mov si, cx
.loop:
mov ah, 0x0c ; 0000: 黑底 1100: 红字
cld ; DF=0,lodsb时使si增1
lodsb ; ds:si --> al
test al, al
jz .end_loop
mov [gs:di], ax
add di, 2
jmp .loop
.end_loop:
ret
times 510-($-$$) db 0
dw 0xaa55
------------------------------------------------------------
setup.asm
------------------------------------------------------------
;; Program: setup.asm
;; Purpose: 设置好保护模式的环境,加载内核,然后把控制权交给内核。
;; Date: 2011-3-9 19:42
;; Author: mofaph <mof...@gmail.com>
;; jmp setup_start
org 0x0500
setup_start:
mov ax, 0xb800
mov gs, ax ; Mono text video buffer
mov ah, 0x0c ; 0000: 黑底 1111: 白字
mov al, 'S'
mov [gs:((80 * 10 + 39) * 2)], ax ; 屏幕第 10 行, 第 39 列。
jmp $ ; Start
;; end of setup.asm
------------------------------------------------------------
mofaph
2011/3/22
我忘记加上 Makefile 文件啦,不好意思。
Makefile:
AS=nasm
OBJS=bootsect setup
.PHONY: all image clean
all: $(OBJS) image
bootsect: bootsect.asm
$(AS) bootsect.asm -o bootsect
setup: setup.asm
$(AS) setup.asm -o setup
image: bootsect
dd if=bootsect of=a.img bs=512 count=1 conv=notrunc
dd if=setup of=a.img bs=512 count=2 seek=1 conv=notrunc
clean:
rm -f $(OBJS)
mofaph
2011/3/22
--
Best regards!
Fam Zheng
0x500这段内存属于BIOS,最好避开,不要往里面放东西。
可以在setup_start处加一个jmp $,然后用虚拟机的调试功能查看cs:ip是不是0x50:0,如果int
0x13调用的参数是对的,应该能够看到,而且可以反汇编看一下0x500处的代码,是不是setup的代码。
> 可以在setup_start处加一个jmp $,然后用虚拟机的调试功能查看cs:ip是不是0x50:0,如果int
> 0x13调用的参数是对的,应该能够看到,而且可以反汇编看一下0x500处的代码,是不是setup的代码。
我找到了这个 BIOS 的分布的信息:
0x00000~0x003FF Interrupt Vector(256*4B=1024B)\\
0x00400~0x004FF BIOS Data Area\\
------------------------------------------------------------
0x00500~0x07BFF Free Memory Area\\
0x07C00~0x07DFF Boot Sector(512B)\\
0x07E00~0x9FC00 Free Memory Area\\
------------------------------------------------------------
0x9FC01~0x9FFFF Extended BIOS Data Area (usually 1K)\\
0xA0000~0xAFFFF EGA/VGA/XGA/XVGA Graphic Video Buffer\\
0xB0000~0xB7FFF Mono text video buffer\\
0xB8000~0xBFFFF CGA/EGA+ Chroma text video buffer\\
0xC0000~0xFDFFF BIOS Routine \& Card BIOS\\
0xFE000~0xFFFF0 BIOS Boot Block\\
0xFFFF1~0xFFFFF
0x00500~0x07BFF 这段内存刚好是自由内存区,所以我觉得放到这里应该
没有问题。
反汇编 0x500 的结果:
<bochs:5> u 0x500 0x50f
00000500: ( ): jmp .+74 ; e94a00
00000503: ( ): nop ; 90
00000504: ( ): dec sp ; 4c
00000505: ( ): outsw dx, word ptr ds:[si] ; 6f
00000506: ( ): popa ; 61
00000507: ( ): imul bp, word ptr fs:[bp+103],
0x6c20 ; 64696e67206c
0000050d: ( ): outsw dx, word ptr ds:[si] ; 6f
0000050e: ( ): popa
段寄存器的值:
<bochs:6> sreg
es:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed
cs:0xf000, dh=0x0000930f, dl=0x0000ffff, valid=3
Data segment, base=0x000f0000, limit=0x0000ffff, Read/Write, Accessed
ss:0x0050, dh=0x00009300, dl=0x0500ffff, valid=7
Data segment, base=0x00000500, limit=0x0000ffff, Read/Write, Accessed
ds:0x0040, dh=0x00009300, dl=0x0400ffff, valid=1
Data segment, base=0x00000400, limit=0x0000ffff, Read/Write, Accessed
fs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed
gs:0xb800, dh=0x0000930b, dl=0x8000ffff, valid=7
Data segment, base=0x000b8000, limit=0x0000ffff, Read/Write, Accessed
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1
gdtr:base=0x000fb997, limit=0x30
idtr:base=0x00000000, limit=0x3ff
寄存器的值:
<bochs:7> r
eax: 0x00000040 64
ecx: 0x00000200 512
edx: 0x00000000 0
ebx: 0x00000040 64
esp: 0x00009f78 40824
ebp: 0x00009f7c 40828
esi: 0x000e0014 917524
edi: 0x00000c9e 3230
eip: 0x00000601
eflags 0x00000246: id vip vif ac vm rf nt IOPL=0 of df IF tf sf ZF af PF cf
2011/3/22 mofaph <mof...@gmail.com>:
> --
> You received this message because you are subscribed to the Google
> Groups "自己动手写操作系统" group.
> To post to this group, send email to osfrom...@googlegroups.com
> To unsubscribe from this group, send email to
> osfromscratc...@googlegroups.com
> For more options, visit this group at
> https://groups.google.com/group/osfromscratch?hl=en
>
--
Best regards!
Fam Zheng