不能进入 setup/loader

5 views
Skip to first unread message

mofaph

unread,
Mar 22, 2011, 9:56:56 AM3/22/11
to osfrom...@googlegroups.com
大家好。

我写了两个文件。一个文件是 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

mofaph

unread,
Mar 22, 2011, 10:06:08 AM3/22/11
to osfrom...@googlegroups.com
2011/3/22 mofaph <mof...@gmail.com>:

我忘记加上 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

Feiran Zheng

unread,
Mar 22, 2011, 10:05:44 AM3/22/11
to osfrom...@googlegroups.com, mofaph
2011/3/22 mofaph <mof...@gmail.com>:

> 大家好。
>
> 我写了两个文件。一个文件是 bootsect.asm,另一个是 setup.asm。
>
> bootsect 的作用是把 setup 加载到内存地址 0x00500 处,显示一点提示信息,然
> 后跳转到 setup 中执行。在 setup 中,在屏幕第 10 行 39 列显示一个黑底红
> 字的字母“S”。
>
> 刚才说过 bootsect 显示一些提示信息,这些提示信息是:
> Loading loader.
> load loader ok.
> Jumping to setup.
>
> 因为我没有写换行,所以都在同一行显示。
>
> 现在问题是,我没有发现红色的字符“L”。
没懂,请问到底是红色的L还是S?
> --
> 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

Feiran Zheng

unread,
Mar 22, 2011, 10:35:22 AM3/22/11
to osfrom...@googlegroups.com
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
>

0x500这段内存属于BIOS,最好避开,不要往里面放东西。

可以在setup_start处加一个jmp $,然后用虚拟机的调试功能查看cs:ip是不是0x50:0,如果int
0x13调用的参数是对的,应该能够看到,而且可以反汇编看一下0x500处的代码,是不是setup的代码。

mofaph

unread,
Mar 22, 2011, 10:51:29 AM3/22/11
to osfrom...@googlegroups.com
2011/3/22 Feiran Zheng <fam...@gmail.com>:

> 可以在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

Feiran Zheng

unread,
Mar 22, 2011, 11:09:42 AM3/22/11
to osfrom...@googlegroups.com, mofaph
为什么在0x500处的汇编是你bootsect的代码而不是start的?是不是int 0x13的参数没写对?

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

Reply all
Reply to author
Forward
0 new messages