鱼C论坛

 找回密码
 立即注册
查看: 3742|回复: 8

[已解决]反汇编Bios中断例程的方法求教

[复制链接]
发表于 2017-6-1 17:39:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
反汇编Bios中断例程的方法求教
       
思路:

1        电脑启动后,会进入实模式,从0000:0000处创建中断向量表;
2        BIOS中断程序被加载到了内存中;
3        CPU跳至0000:7c00处执行引导程序。

        因此,我用汇编写好引导程序,加入写软盘功能,将0000:0000~FFFF:FFFF的内存全部写入到软盘,然后利用反汇编工具对其反汇编以得到BIOS中断程序的汇编代码。
       
       
行动步骤:

1        用虚拟机(VirtualBox)创建一台电脑;
2        虚拟两个软驱;
3        在linux下利用nasm编译引导程序(boot),生成.bin文件,然后使用linux的dd命令(如dd if=boot.bin of=boot.img)将其虚拟成软盘镜像。
4        继续使用dd命令创建一个空白软盘镜像(dd if=/dev/zero of=blank.img bs=1474560 count=1)。bs的作用是限制大小,1474560=1.44m软盘(不知道对不对)
5        分别将两个镜像装进软驱,从0号软盘启动虚拟电脑。出现问候后按回车执行写软盘程序。
6        将0000:0000~FFFF:FFFF的内存全部写入到1号软盘。

进行到这里,问题来了:
1        内存中的数据有一部分成功写入到了空白软盘,内存F000:0000以后应该有数据的,可是软盘里没有,连0000:FC00的数据都没有写入软盘,应该是我的 写软盘代码 有问题。
2        上述思路和步骤是否存在问题,大神们能否指点一下。

3        读软盘的程序也有问题,本想把软盘内容读到0000:7e00处,可直接将es=0000h,bx=7e00h的话程序会卡死,将es=07e0h,bp=0的话可以读,但是读到的内存位置变成了07e0:000a
3        代码附后,因为是刚刚从MASM转入学习NASM,代码可能不太好读,请大神包涵。


  1. org 07c00h       

  2.         mov ax,cs                        ;显示问候
  3.         mov es,ax
  4.         mov ax,BootMessage
  5.         mov bp,ax
  6.         mov cx,6
  7.         mov dx,0
  8.         call showgreen               

  9.         mov ch,00000000b        ;设置光标形状
  10.         mov cl,00010000b
  11.         mov ah,01h                        ;中断入口
  12.         int 10h
  13.        
  14.        
  15.         call newline                ;换行

  16.        
  17. r16h:       
  18.         mov ah,0                        ;等待键盘输入
  19.         int 16h
  20.         mov ah,0eh                        ;将输入输出至屏幕
  21.         mov bx,00001010b
  22.         mov cx,1
  23.         int 10h
  24.        
  25.         cmp al,0dh                        ;回车键结束输入
  26.         je COPY
  27.         jne r16h

  28. COPY:                                        ;写软盘程序,第一段写一个柱面
  29.         push es                               
  30.         mov si,0                        ;计数器
  31.         mov ax,0h
  32.         mov es,ax                        ;内存基地址
  33.         mov bx,0h                        ;内存偏移地址
  34.         mov ah,03h                        ;int13h 写扇区入口
  35.         mov al,18                        ;写扇区的数量
  36.         mov ch,0                        ;柱面 或者说 磁道
  37.         mov cl,1                        ;第一个扇区开始
  38.         mov dh,0                        ;驱动号 或者说 盘面号
  39.         mov dl,1                        ;驱动器号 0~7f h 软盘
  40.         int 13h
  41.        
  42. go:        push ax                                ;储存参数,以便开始写第二个柱面
  43.         mov ax,es                       
  44.         add ax,240h                        ;下一个内存基地址
  45.         mov es,ax
  46.         mov bx,0
  47.         pop ax
  48.         inc ch                                ;下一个柱面或者说磁道
  49.         inc si                                ;计数器加1
  50.         cmp si,80                        ;如果写够了80个磁道,就需要换盘面了                               
  51.         je C_1
  52.         int 13h
  53.         jmp go
  54. C_1:                                        ;写软盘第二盘面
  55.         mov si,0                        ;计数器重新清零
  56.         push ax
  57.         mov ax,es                       
  58.         add ax,240h
  59.         mov es,ax                        ;内存基地址
  60.         mov bx,0                        ;内存偏移地址
  61.         pop ax
  62.         mov ch,0                        ;柱面 或者说 磁道
  63.         mov cl,1                        ;第一个扇区开始
  64.         mov dh,1                        ;驱动号 或者说 盘面号
  65.         mov dl,1                        ;驱动器号 0~7f h 软盘
  66.         int 13h
  67.        
  68. go1:       
  69.         push ax                                ;储存参数
  70.         mov ax,es                       
  71.         add ax,240h                        ;下一个内存基地址
  72.         mov es,ax
  73.         mov bx,0
  74.         pop ax
  75.         inc ch                                ;下一个磁道
  76.         inc si                                ;计数器加1
  77.         cmp si,33                        ;如果写够了113个磁道,就写了FE400个数据了       
  78.                                                 ;如果直接写114个磁道,es=FE40 + 240 =10080将产生溢出
  79.         je C_end
  80.         int 13h
  81.         jmp go1
  82.        
  83. C_end:       
  84.         mov bx,2400h                ;继续多写入一个磁道,写够100800 h个数据
  85.         inc ch
  86.         int 13h
  87.        
  88.         mov al,'o'                        ;显示一个o,表示程序可以执行到这一步
  89.         mov ah,0eh
  90.         mov bx,00001010b
  91.         mov cx,1
  92.         int 10h
  93.         pop es
  94.         jmp r16h                        ;跳回等待输入

  95. showgreen:                                ;以绿色显示指定位置的字符串,需要设置es,bp,cx,dx
  96.         mov ax,01301h
  97.         mov bx,00001010b
  98.         int 10h
  99.         ret

  100. loadf:                                        ;读软盘子程序
  101.                                                 ;读取软盘1至7e00 可软盘内容是复制到了7e0a 前9个位置留空了,为什么?
  102.         push es
  103.         mov ax,07e0h
  104.         mov es,ax
  105.         mov bp,0h
  106.         mov ah,2                        ;int13 入口参数
  107.         mov al,2                        ;读取两个扇区
  108.         mov cx,0001h                ;从第一扇区开始
  109.         mov dx,0001h                ;1号驱动器(0~80为软驱
  110.         int 13h
  111.         pop es
  112.         ret
  113.        
  114.        
  115. newline:
  116.         mov        ah,03h                        ;获取光标位置
  117.         int 10h       
  118.         inc dh                                ;设置光标位置,换行
  119.         mov dl,0                        ;行首
  120.         mov ah,02h                        ;
  121.         int 10h
  122.         ret
  123.        
  124. BootMessage:        db "Hello!"                                ; 6byte
  125. Smessage:                db "Well come to Buu"        ; 16byte
  126. Load:        db "Load successfully..."
  127.                 db 0ah
  128.                 db "Do you want to continue? "        ; System-Load byte
  129.                 db "Press ENTER"
  130. System:        dw 0h,07e1h                ; 系统入口地址       

  131. times 510-($-$)        db 0
  132. dw 0xaa55
复制代码

       
       
       
最佳答案
2017-6-1 20:59:46
这个问题有意思,我感兴趣,我找个时间给你试一下
^_^
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2017-6-1 20:59:46 | 显示全部楼层    本楼为最佳答案   
这个问题有意思,我感兴趣,我找个时间给你试一下
^_^
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-2 21:04:10 | 显示全部楼层
人造人 发表于 2017-6-1 20:59
这个问题有意思,我感兴趣,我找个时间给你试一下
^_^

又麻烦你了  哈哈~!
我已经解决了大部分问题了。原代码的COPY~C_end段代码有问题。
1、linux生成的软盘镜像不是18个扇区每道,而是36扇区每道。
2、我原来忽略了第一次写软盘后的ah、al返回值,导致第二次写软盘入口错误。
正确的代码如下:

  1. COPY:                                                ;写入磁盘程序
  2.         push es                               
  3.         mov si,0                        ;计数器
  4.         mov ax,0
  5.         mov es,ax                        ;内存基地址
  6.         mov bx,0                        ;内存偏移地址
  7.         mov ah,03h                        ;int13h 写扇区入口
  8.         mov al,36                        ;写扇区的数量 *** 这里必须星标一下 软盘镜像 居然不是18个扇区每道的。。。
  9.         mov ch,0                        ;柱面 或者说 磁道
  10.         mov cl,1                        ;第一个扇区开始
  11.         mov dh,0                        ;驱动号 或者说 盘面号
  12.         mov dl,0                        ;驱动器号 0~7f h 软盘
  13.         int 13h
  14.        
  15. go:       
  16.         mov ax,es                       
  17.         add ax,480h                        ;下一个内存基地址
  18.         mov es,ax
  19.         mov ah,03h
  20.         mov al,36
  21.         inc ch                                ;下一个磁道
  22.         inc si                                ;计数器加1
  23.         cmp si,56                        ;如果写够了56个磁道,就需要换盘面了        ,但这里不需要换面,镜像也好像没有第二面                       
  24.         je C_end
  25.         int 13h
  26.         jmp go
  27. C_end:       
  28.         mov bx,4800h                ;因为此时es=fc00,不能再加480h了,加了=10080h 会溢出 所以直接修改偏移地址
  29.         inc ch
  30.         mov ah,03h
  31.         mov al,18                        ;暂定写18个扇区 此时已经超过1m数据了
  32.         int 13h
  33.        
  34.         mov al,'o'
  35.         mov ah,0eh
  36.         mov bx,00001010b
  37.         mov cx,1
  38.         int 10h
  39.         pop es
  40.         jmp r16h
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-2 21:13:42 | 显示全部楼层
自己解答一下,附虚拟机的1M内存数据,里边包含了中断向量表以及应该包含了BIOS中断例程,如果有兴趣的朋友了自己反汇编看看。我如果弄懂了也会把每个中断的学习情况慢慢发上来。

non.rar

80.26 KB, 下载次数: 2

光盘镜像文件,包含了实模式下1M内存的所有数据

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-2 21:22:12 | 显示全部楼层
人造人 发表于 2017-6-1 20:59
这个问题有意思,我感兴趣,我找个时间给你试一下
^_^

有没有好用的反汇编工具? 能够输入地址如 f000:efee 直接定位到该地址的? 我现在在用W32dsm 好像不是很方便,因为他的地址是  1.ffff 这样的 不是基地址加偏移 ,而是一个10进制数 加后边一个16进制地址
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-2 21:37:54 | 显示全部楼层
bin2yx 发表于 2017-6-2 21:22
有没有好用的反汇编工具? 能够输入地址如 f000:efee 直接定位到该地址的? 我现在在用W32dsm 好像不是很 ...

ndisasm

这是nasm 文件夹下的一个小工具
http://www.nasm.us/
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-3 18:26:57 | 显示全部楼层
无标题.png
bios.zip (166.11 KB, 下载次数: 8)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-4 22:23:03 | 显示全部楼层

谢谢你的文件,我自己也能弄出来了。
还有个问题,我写的将内存0000:0000~FFFF:FFFF全部拷入软盘的代码还是有问题,虽然能拷贝大部分内存,但是每完成拷贝两个或者三个磁道后就会出一次错误,int13h的 ah返回值是 09H — DMA超过64K界限,出错以后的下几次循环又能成功,这就导致了小部分内存没有拷入软盘。我目前正在试着解决,可是很难。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-4 22:39:30 | 显示全部楼层
bin2yx 发表于 2017-6-4 22:23
谢谢你的文件,我自己也能弄出来了。
还有个问题,我写的将内存0000:0000~FFFF:FFFF全部拷入软盘的代码 ...

我正在从另一个角度解决这个问题,你的程序中是使用BIOS中断写软盘,BIOS中断的程序也在0000:0000~FFFF:FFFF
会不会是拿它本身拷贝它,出了问题?
因为我并不清楚BIOS中断是如何写的软盘,如果要用它来复制它本身,是否可以?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-12 23:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表