《操作系统真象还原》学习笔记
1. mbr.S
-
org 0x7C00
-
mov ax, cs
-
mov ds, ax
-
mov es, ax
-
mov ss, ax
-
mov ax, 0xb800
-
mov gs, ax
-
-
;print 1MBR
-
mov byte [gs:0x00], '1'
-
mov byte [gs:0x01], 0xA4
-
-
mov byte [gs:0x02], 'M'
-
mov byte [gs:0x03], 0xA4
-
-
mov byte [gs:0x04], 'B'
-
mov byte [gs:0x05], 0xA4
-
-
mov byte [gs:0x06], 'R'
-
mov byte [gs:0x07], 0xA4
-
-
;loader loader.bin to 0x9000
-
mov bx, 0x9000 ;dst_add in memory
-
mov cl, 1 ;sector cnt of disk
-
mov eax, 2 ;LBA addr 从第2个扇区开始读数据
-
call load_disk
-
-
;jmp to 0x9000
-
jmp 0x9000
-
-
load_disk:
-
;eax --> src_addr of disk, in the format of LBA
-
;bx --> memory dst_addr
-
;cx --> sector_count
-
mov edx, eax
-
mov di, cx
-
-
mov dx, 0x1f2 ;sector count
-
mov al, cl
-
out dx, al
-
-
mov eax, edx ;LBA-->0-8
-
mov dx, 0x1f3
-
out dx, al
-
-
mov cl, 8
-
shr eax, cl ;LBA--> 8-16
-
mov dx, 0x1f4
-
out dx, al
-
-
shr eax, cl ;LBA-->16-24
-
mov dx, 0x1f5
-
out dx, al
-
-
shr eax, cl ;LBA-->16-24
-
and al, 0x0f
-
or al, 0xe0
-
mov dx, 0x1f6
-
out dx, al
-
-
mov dx,0x1f7 ;send read cmd
-
mov al, 0x20
-
out dx, al
-
-
not_ready:
-
in ax, dx
-
and ax,0x88
-
cmp ax,0x88
-
jnz not_ready
-
-
mov ax, di
-
mov dx, 256
-
mul dx
-
mov cx, ax
-
mov dx, 0x1f0
-
goon_read:
-
in ax, dx
-
mov [bx], ax
-
add bx, 2
-
loop goon_read
-
ret
-
-
jmp $
-
times 510-($-$$) db 0
-
dw 0xaa55
2. loader.S
-
cong@msi:/work/os/code/2loader$ cat loader.S
-
org 0x9000
-
mov ax, cs
-
mov ds, ax
-
mov es, ax
-
mov ss, ax
-
mov ax, 0xb800
-
mov gs, ax
-
-
mov byte [gs:0x08], '2'
-
mov byte [gs:0x09], 0xA4
-
-
mov byte [gs:0x0A], 'L'
-
mov byte [gs:0x0B], 0xA4
-
-
mov byte [gs:0x0C], 'O'
-
mov byte [gs:0x0D], 0xA4
-
-
mov byte [gs:0x0E], 'A'
-
mov byte [gs:0x0F], 0xA4
-
-
mov byte [gs:0x10], 'D'
-
mov byte [gs:0x11], 0xA4
-
-
jmp $
3. Makefile
-
cong@msi:/work/os/code/2loader$ cat Makefile
-
ALL: mbr loader
-
mbr:
-
nasm mbr.S -o mbr.bin
-
loader:
-
nasm loader.S -o loader.bin
-
clean:
-
-rm *.o mbr.bin loader.bin
-
flash:
-
-rm ../disk.img
-
dd if=/dev/zero of=../disk.img bs=1M count=30
-
dd if=./mbr.bin of=../disk.img bs=512 count=1 conv=notrunc
-
dd if=./loader.bin of=../disk.img bs=512 count=10 seek=2 conv=notrunc //seek=2,跳过了(0与1)2个扇区
0 1 2
0--200 200-400 400-600
4. 检查一下disk.img是不是从0x400-0x600之间有数据
loader.bin的
-
cong@msi:/work/os/code/2loader$ xxd ./loader.bin
-
0000000: 8cc8 8ed8 8ec0 8ed0 b800 b88e e865 c606 .............e..
-
0000010: 0800 3265 c606 0900 a465 c606 0a00 4c65 ..2e.....e....Le
-
0000020: c606 0b00 a465 c606 0c00 4f65 c606 0d00 .....e....Oe....
-
0000030: a465 c606 0e00 4165 c606 0f00 a465 c606 .e....Ae.....e..
-
0000040: 1000 4465 c606 1100 a4eb fe ..De.......
disk.img中的loader.bin
-
cong@msi:/work/os/code/2loader$ xxd -seek 0x400 -l 0x200 ../disk.img ;-seek是从偏移多少开始打印,-l是打印多少字符
-
0000400: 8cc8 8ed8 8ec0 8ed0 b800 b88e e865 c606 .............e..
-
0000410: 0800 3265 c606 0900 a465 c606 0a00 4c65 ..2e.....e....Le
-
0000420: c606 0b00 a465 c606 0c00 4f65 c606 0d00 .....e....Oe....
-
0000430: a465 c606 0e00 4165 c606 0f00 a465 c606 .e....Ae.....e..
-
0000440: 1000 4465 c606 1100 a4eb fe00 0000 0000 ..De............
-
0000450: 0000 0000 0000 0000 0000 0000 0000 0000 ................
-
0000460: 0000 0000 0000 0000 0000 0000 0000 0000 ................
这不就对上了嘛,说明刷到disk.img的loader.bin己在disk.img的正确位置上
二.调试
2.1 只打印出了1MBR
-
<bochs:2> b 0x9000
-
<bochs:3> c
-
(0) Breakpoint 2, 0x00009000 in ?? ()
-
Next at t=156817011
-
(0) [0x000000009000] 0000:9000 (unk. ctxt): add byte ptr ds:[bx+si], al ; 0000
-
<bochs:4> u /10
-
00009000: ( ): add byte ptr ds:[bx+si], al ; 0000
-
00009002: ( ): add byte ptr ds:[bx+si], al ; 0000
-
00009004: ( ): add byte ptr ds:[bx+si], al ; 0000
-
00009006: ( ): add byte ptr ds:[bx+si], al ; 0000
-
00009008: ( ): add byte ptr ds:[bx+si], al ; 0000
-
0000900a: ( ): add byte ptr ds:[bx+si], al ; 0000
-
0000900c: ( ): add byte ptr ds:[bx+si], al ; 0000
-
0000900e: ( ): add byte ptr ds:[bx+si], al ; 0000
-
00009010: ( ): add byte ptr ds:[bx+si], al ; 0000
-
00009012: ( ): add byte ptr ds:[bx+si], al ; 0000
这说明在0x9000处没有代码
b.重启bochs调试发现从in ax, dx时,读取出来的数据都为0
-
(0) [0x000000007c96] 0000:7c96 (unk. ctxt): in ax, dx ; ed
-
<bochs:7> r -->r 指令打印寄存器的值
-
eax: 0x00000100 256 -->执行in ax,dx之前eax=0x100
-
ecx: 0x00090100 590080
-
edx: 0x000001f0 496
-
ebx: 0x00009000 36864
-
esp: 0x0000ffd4 65492
-
ebp: 0x00000000 0
-
esi: 0x000e0000 917504
-
edi: 0x00000001 1
-
eip: 0x00007c96
-
eflags 0x00000006: id vip vif ac vm rf nt IOPL=0 of df if tf sf zf af PF cf
-
<bochs:8> s -->s单步与n的区别是call之后的函数s会进,n不进
-
Next at t=156815985
-
(0) [0x000000007c97] 0000:7c97 (unk. ctxt): mov word ptr ds:[bx], ax ; 8907
-
<bochs:9> r -->r 指令打印寄存器的值
-
eax: 0x00000000 0 -->执行in ax,dx后eax=0x0000,说明硬盘读操作读到的数据为0
-
ecx: 0x00090100 590080
-
edx: 0x000001f0 496
-
ebx: 0x00009000 36864
-
esp: 0x0000ffd4 65492
-
ebp: 0x00000000 0
-
esi: 0x000e0000 917504
-
edi: 0x00000001 1
-
eip: 0x00007c97
c.
L35行edx来保存eax的值,但是接着L3行就将dx设为0x1f2,把保存的eax值破坏了
d.
not_ready:
in ax, dx --> in 指令是8位的,这会使ax=0xFFFF
and ax,0x88 --> and 之后ax=0x88
cmp ax,0x88 --> cmp操作一定相等,所以读到到的值为0了。
2.2 正确的代码打包
2loader.rar (下载后改名为2loader.tar.gz)
2.3正确的运行结果
阅读(1299) | 评论(0) | 转发(0) |