|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
2017.7.8
断断续续看了几天书,收获不多,脑子里翻来覆去就是自己的系统到底该怎么做。
MLGB的,MS-DOS1.0版本,1981年8月发布,仅支持单面软盘。它到底是怎么做到的?
哪里能找到这东西的解剖版啊,我好想弄明白怎么不用int 13 控制软驱...
前段时间逐条注释int 13,这几天也暂停了,工作量太大了,未知的东西也太多了,今天发一段代码上来,万一哪个有空的兄弟帮提点一下也能省我好多功夫。
文件中0000EC5B处应该是int 13的入口
实模式下内存F000:0000~F000:FFFF 反汇编代码:
文件附后。
我自己的注释也发一发,虽然还没完成,虽然可能仅仅是起了个头:
- ;Int 13h
-
- jmp a
- a:
- cmp ah,0x4a
- jc b ;CF进位时跳转(意思是小于4a跳转?)
- cmp ah,0x4d
- ja b ;无符号大于跳转
- pushaw ;将8个通用寄存器入栈
- push es
- push ds
- push cs
- pop ds ;ds=cs
- cld ;正向?
- push word 0xece9;这里暂且不用管他的具体数值,因为读写磁盘不用到这里
- jmp word 0x3c0c ;
- b:
- push es ;读写软盘时跳到这里
- push ax
- push bx
- push cx
- push dx
- call onecall ;第一CALL
- cmp al,0x0 ;al=[es:336h]=[[word 0040:000e]:336h] 查证后 al=0
- jz c ;好像是为0跳转
-
- call twocall ;******这里应该暂时不用管 因为 还没有到这里******
-
-
- c: ;第一CALL al=[9fc0:336h]=[9ff3:6]=0后跳到这里 等于前边什么都没做
- ;[9ff3:6] 在 EBDA(Extended BIOS Data Area)扩展BIOS数据区
- pop dx
- pop cx
- pop bx
- pop ax
- pop es
- push ax
- push cx
- push dx ;
- push bx
- push dx
- push bp
- push si
- push di
- push es ;bp+6
- push ds ;bp+4
- push cs ;这两步是设置DS=CS
- pop ds
- cld
- test dl,0x80 ;TEST dl,bl 与 AND dl,bl 差不多,根据结果设置标志寄存器,结果本身不会保存
- ;这里应该是判断是选择什么驱动器的,因为80~ff是硬盘 80h 的2进制是 1000 0000
- jnz 0xecc8 ;这里的意思是大于80h 就跳转暂时我不读写硬盘,先不管跳哪
- push word 0xece9;bp+2
- jmp word 0x3288 ;我们如果读写软盘,就会从这里起跳
-
- d:
- push bp
- mov bp,sp
- push si
- push di
- sub sp,byte +0x16 ;这里是啥意思啊? 栈指针减16h(22),留出22个内存?
- mov bx,[bp+0x16] ;bx=ax这是什么意思?好像这个内存值是ax的值
- shr bx,0x8 ;bl=ah假如是ax值 ,那么这里就是取aH的值,int13入口 哈哈
- mov [bp-0x8],bl ;入口值ah存入 [ss:bp-8]
- mov si,[bp+0x16] ;si=ax
- and si,0xff ;si低位清零
- mov al,[bp+0xe] ;al=dl 但是这里不太清楚是高位还是低位***???应该是低位
- mov ah,[bp+0x14] ;ah=cl
- mov cl,[bp+0x16] ;cl=al
- mov dx,[bp+0x14] ;dx=cx
- shr dx,0x8 ;dl=ch
- mov [bp-0x12],dx ;cx存入 [ss:bp-0x12]
- cmp bl,0x8 ;将入口值ah与8比
- jc e ;借位时跳转 读写都是小于8 所以这里跳转
-
- e:
- cmp bl,0x1
- jc 0x3309 ;小于1跳转? 很明显读写值大于1,所以暂且不管他
- jna word 0x3382 ;无符号不大于跳转,意思是小于等于跳转,暂且不管他
- cmp bl,0x5
- jz word 0x36cc ;等于5时跳转,还是不管他
- cmp bl,0x4
- jna word f ;无符号不大于跳转,意思是小于等于跳转,啊哈哈 是他是他就是他
-
- f:
- mov ch,cl ;ch=al(入口值,要读写的扇区数)
- mov dl,[bp-0x12] ;dl=cl(入口值,起始扇区号)
- mov [bp-0xa],dl ;cl(入口值,起始扇区号)存入[bp-0xa]
- mov [bp-0x6],ah ;cl(入口值,起始扇区号)存入[bp-0x6]
- mov dx,[bp+0x12] ;dx=dx(入口值,
- shr dx,0x8 ;dl=dh(入口值,磁头号)
- mov [bp-0xe],dl ;dh(入口值,磁头号)存入[bp-0xe]
- mov [bp-0xc],al ;dl(入口值,驱动器号)存入[bp-0xc]
- cmp al,0x1 ;此时al=入口的dl值驱动器号*****??????????
- ja 0x33c9 ;无符号大于1跳转,我用1号软驱读写,不管他
- cmp dl,0x1 ;此时dl=磁头号 也就是入口时的dh,与1比
- ja 0x33c9 ;大于跳,我应该只读写两面,也就是0~1,所以这个不管他
- test cl,cl ;测试要读写的扇区数
- jz 0x33c9 ;为0跳,我要读写肯定不为0,所以不管他
- cmp cl,0x48 ;测试要读写的扇区数是否大于48h
- jna g;0x33f3 ;小于等于就跳 就跳
-
- g:
- movzx ax,[bp-0xc] ;高位扩展为0 即 ax=0000+dl(dl为入口值)
- call gcall ;word 0x3264 应该快接近真相了吧
- test ax,ax ;ax=1或者0,这是从71h端口读出的一个数值处理后得到
- jz word 0x3500 ;为0时跳,***暂时先不理会***
- ;假设ax=1,执行下列命令
- movzx dx,[bp-0xc] ;高位扩展为0 即 dx=0000+dl(dl为入口值)
- mov ax,dx ;ax=dl(dl为入口值)
- call g2call ;word 0x30a9
- test ax,ax
-
-
-
-
- g2call:
- push bp
- mov bp,sp
- push bx
- push dx
- mov bx,ax ;bx=dl(dl为入口值)
- mov dx,0x3e
- mov ax,0x40
- call onecalltwo ;word 0x16b8 又去查bios数据区;
- ;40:003e表示磁盘驱动器的搜索状态。
- ;如果这些位中有一位为0,则表示在搜索磁道之前,必须重新校准相应的驱动器。
- ;位4-6未使用,位7为中断标志位,为1表示中断发生
- ;BIOS数据区说明 https://wenku.baidu.com/view/5c865a2aeff9aef8941e06d8.html
- mov ah,al ;ah=al=多少呢? 暂时先不理会***
- test bx,bx ;bx=dl(dl为入口值)
- jz 0x30c1 ;dl不为0,不跳
- shr al,1 ;因为不是0号驱动器,所以al右移1位?
- and al,0x1 ;保留1号驱动的搜索状态
- jnz Ncalibration ;0x30c9 ;看是否需要重新校准? 不为0则跳,为0则往下执行校准
- xor ah,ah
- jmp short 0x30e5
-
- Ncalibration:
- mov dx,0x90 ;dx上一步值为0x3e,再上一步dx=0000+dl(dl为入口值)
- test bx,bx ;bx=dl(dl为入口值)
- jz 0x30d3 ;dl不为0,不跳
- mov dx,0x91
- mov ax,0x40
- call onecalltwo ;word 0x16b8 又去查bios数据区;
- ;40:0091 字节 驱动器1介质状态
- xor ah,ah
- sar ax,0x4 ;SAR是算术右移指令,功能是将操作数右移,符号位保持不变
- ;作用是将AX中的数右移4位,这样就是取al的高4位
- ;第4位 介质已知 5 需要双倍速率
- ;第6~7位 磁盘数据传送速率 00:500K/S 01:300K/S 10:250K/S 11:保留
- ;https://wenku.baidu.com/view/9ba4d2f5ba0d4a7302763a48.html
- and al,0x1 ;此意是查介质是否已知,但是不知道是0为已知还是1为已知
- jz 0x30c5 ;介质是否已知,反正为0跳转,跳了以后会xor ah,ah 然后接下下步
- mov ax,0x1
- lea sp,[bp-0x4] ;介质是否已知,都会跳到这里,不同的是ax=0或者1,到这里我有点接不下去了
- pop dx
- pop bx
- pop bp
- ret ;g2call的 ret
- ;好想放弃了,2万行左右的代码,我这里只看了200来行,花了十来天了
- ;查不到的东西越来越多,好难啊。。。到底该从哪学??
-
- gcall:
- push bp
- mov bp,sp
- push dx ;dx=00dh,入栈(入口值,磁头号)
- mov dx,ax ;dx=00dl,(入口值,驱动器号) 操他妈的换来换去有意思?
- mov ax,0x10 ;ax=0x10
- call gcallcall ;word 0x1714 ;
- test dx,dx ;dx还是=00dl (入口值,驱动器号)
- jnz port70 ;0x3279 ;我要写的是1号软驱,所以这里不为0,跳
- shr al,0x4 ;dl不为0,到不了这一步 上一步就ret了
- jmp short 0x327b
-
- port70:
- and al,0xf ;将al高4位置0
- test al,al ;
- setnz al ;Sets the byte in the operand to 1 if the Zero Flag is clear
- ;otherwise sets the operand to 0
- ;如果ZF标志位为0,al=1 如果ZF标志位为1,al=0
- xor ah,ah ;ah=0
- lea sp,[bp-0x2] ;例行放屁
- pop dx
- pop bp
- ret ;gcall完结点,返回g
-
- gcallcall:
- push bp
- mov bp,sp
- push dx ;dx=00dl,入栈(入口值,驱动器号)
- mov ah,0x70 ;ax=0x7010
- cmp al,0x80 ;al=0x10,和0x80比
- jc here ;0x1720 ;借位跳转,这里是跳的
- mov ah,0x72
- here: ;第一次端口读写操作
- movzx dx,ah ;高位扩展为0,即 dx=00ah=0x0070
- out dx,al ;给70h端口赋值 0x10 ****** 此端口写入数据后不知道会发生什么
- ;70h端口好像是CMOS的端口,给这个端口写入"9,8,7,4,2,0"分别是读年月日,时秒分进71h端口
- ;这里到底是不是CMOS的端口呢??
- ;写入0x10 即从0x10处读取数值,这个数值是什么?就不知道是什么意思了
- ;CMOSRAM 内容:https://wenku.baidu.com/view/de597a671ed9ad51f01df274.html?re=view
- ;Bits 7-4 = Drive 0 type
- ;Bits 3-0 = Drive 1 type
- movzx dx,ah ;高位扩展为0,即 dx=00ah=0x0070
- inc dx ;dx=0x0071
- in al,dx ;读取71h端口一个数进al
- sub ah,ah ;ah=0
- lea sp,[bp-0x2] ;这是在脱裤子放屁吗,lea指令将一个近地址指针写入到指定的寄存器
- ;这里即将ss:[bp-2]的地址赋值给sp,而sp的值本来就是这个嘛
- pop dx ;dx=00dl(入口值,驱动器号)
- pop bp
- ret ;gcallcall 的 ret
-
-
-
-
-
-
- onecall:
- push bp ;保存bp
- mov bp,sp ;bp=sp 等于栈指针此时的数值,6 这之前push了6个寄存器,最后一个是bp
- mov dx,0xe
- mov ax,0x40
- call onecallone
- mov dx,0x366
- call onecalltwo
- mov sp,bp
- pop bp
- ret
-
- onecallone: ;此时dx=0xe ax=0x40
- ;bios数据查询程序,这里查字 单元
- push bx
- push bp
- mov bp,sp ;等于栈指针此时的数值,6 这之前push了8个寄存器,最后一个是bp
- mov bx,dx
- mov es,ax
- mov ax,[es:bx] ;ax=[0040:000e] 这里是BIOS数据区的一个数值,不知道是什么
- pop bp
- pop bx
- ret
- onecalltwo: ;此时dx=0x366 ax=[0040:000e]=9fc0
- ;第二次dx=0x3e ax=0x40
- ;bios数据查询程序,这里查字节 单元
- push bx
- push bp
- mov bp,sp
- mov bx,dx
- mov es,ax ;es=[0040:000e]=9fc0
- mov al,[es:bx] ;al=[9fc0:336h]=[9ff3:6]=0
- pop bp
- pop bx
- ret
-
- twocall:
- push bp
- mov bp,sp
- mov dx,0xe
- mov ax,0x40
- call onecallone
- mov dx,0x368
- call onecalltwo
- mov sp,bp
- pop bp
- ret
复制代码
2017.7.8 |
评分
-
查看全部评分
|