tiny-os icon indicating copy to clipboard operation
tiny-os copied to clipboard

P87, b 0x900 我把 call.bin 放在了内存 0x900 处,所以在此处设置断点,没告诉怎么把call.bin 放在了内存 0x900 处?

Open ScGPS opened this issue 2 years ago • 1 comments

您好! 书中第87页,没有告诉如何把call.bin放到0x900 处? 麻烦给个简单的方法.谢谢!

ScGPS avatar Apr 05 '22 15:04 ScGPS

我解决了这个问题: 核心: 需要写汇编程序自己搬运代码到0x900去.

验证call,ret实验
A. 创建项目文件夹
# 创建文件夹example_chap03_nasm_002/
mkdir -p ~/linux_sources/example_chap03_nasm_002/

==========================================

B. call near近调用例子
B.1 编写1call.S代码
内容:

section call_test vstart=0x900
   call near near_proc
   jmp $
   addr dd 4
near_proc:
   mov ax, 0x1234
   ret

==========================================

B.2 使用Bochs检查机器码
B.2.1 创建mbr.S代码
内容:

SECTION MBR vstart=0x7c00
   mov eax, 0x2         ; 起始扇区lba地址,从间隔第二个扇区开始
   mov bx, 0x900        ; 写入的地址
   mov cx, 1            ; 待读入的扇区数,读取1个扇区内容
   call rd_disk_m_16    ; 以下读取程序的起始部分(一个扇区)

   jmp 0x900

;-------------------------------------------------------------------------------
;功能: 读取硬盘n个扇区
rd_disk_m_16:
;-------------------------------------------------------------------------------
                        ; eax=LBA扇区号
                        ; ebx=将数据写入的内存地址
                        ; ecx=读入的扇区数
      mov esi,eax       ; 备份eax
      mov di,cx         ; 备份cx
; 读写硬盘:
; 第1步: 设置要读取的扇区数
      mov dx,0x1f2
      mov al,cl
      out dx,al         ; 读取的扇区数
      mov eax,esi       ; 恢复ax
; 第2步: 将LBA地址存入0x1f3 ~ 0x1f6
      ; LBA地址7~0位写入端口0x1f3
      mov dx,0x1f3
      out dx,al                          
      ; LBA地址15~8位写入端口0x1f4
      mov cl,8
      shr eax,cl
      mov dx,0x1f4
      out dx,al
      ; LBA地址23~16位写入端口0x1f5
      shr eax,cl
      mov dx,0x1f5
      out dx,al
      shr eax,cl
      and al,0x0f       ; lba第24~27位
      or al,0xe0        ; 设置7~4位为1110,表示lba模式
      mov dx,0x1f6
      out dx,al
; 第3步: 向0x1f7端口写入读命令,0x20
      mov dx,0x1f7
      mov al,0x20
      out dx,al
; 第4步: 检测硬盘状态
  .not_ready:
      ;同一端口,写时表示写入命令字,读时表示读入硬盘状态
      nop
      in al,dx
      and al,0x88        ; 第4位为1表示硬盘控制器已准备好数据传输,第7位为1表示硬盘忙
      cmp al,0x08
      jnz .not_ready     ; 若未准备好,继续等.
; 第5步: 从0x1f0端口读数据
      mov ax, di
      mov dx, 256
      mul dx
      mov cx, ax         ; di为要读取的扇区数,一个扇区有512字节,每次读入一个字,
                         ; 共需di*512/2次,所以di*256
      mov dx, 0x1f0
  .go_on_read:
      in ax,dx
      mov [bx],ax
      add bx,2
      loop .go_on_read
      ret

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

==========================================

B.2.2 编译
cd ~/linux_sources/example_chap03_nasm_002/
rm -rf *.bin *.lock
nasm -o 1call.bin 1call.S
nasm -o mbr.bin mbr.S

# 使用bximage命令生成虚拟硬盘
bximage --> 1 --> hd --> flat --> 60 --> hd60M.img

# 使用dd命令将操作系统写入硬盘镜像(写入数据到镜像中)
cd ~/linux_sources/example_chap03_nasm_002/
dd if=mbr.bin of=hd60M.img bs=512 count=1 conv=notrunc
dd if=1call.bin of=hd60M.img bs=512 count=1 seek=2 conv=notrunc

==========================================

B.2.3 配置bochs配置文件
cd ~/linux_sources/example_chap03_nasm_002/
vi bochsrc_1call.disk
内容:

# Bochs配置文件

# 机器内存: 32MB
megs: 32

# 启动方式
boot: disk

# 关闭鼠标
mouse: enabled=0

# 硬盘设置 
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="hd60M.img", mode=flat, cylinders=121, heads=16, spt=63

==========================================

B.2.4 测试
# 启动bochs
# Applications-->System Tools-->Terminal
cd ~/linux_sources/example_chap03_nasm_002/
rm -rf *.lock
bochs -f bochsrc_1call.disk
--> 6

b 0x900
c
到0x900后
u 0x900 0x920
输出:
00000900: (                    ): call .+6                  ; e80600
00000903: (                    ): jmp .-2                   ; ebfe
00000905: (                    ): add al, 0x00              ; 0400
00000907: (                    ): add byte ptr ds:[bx+si], al ; 0000
00000909: (                    ): mov ax, 0x1234            ; b83412
0000090c: (                    ): ret                       ; c3
...
这是期望的结果.

Ctrl+C-->quit
就退出Bochs环境了.

ScGPS avatar Apr 09 '22 08:04 ScGPS