鱼C论坛

 找回密码
 立即注册
查看: 2843|回复: 0

[学习笔记] 和CPU说话05

[复制链接]
发表于 2017-7-8 16:23:58 | 显示全部楼层 |阅读模式

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

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

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

F0000~FFFFF.rar

128.19 KB, 下载次数: 1

实模式下F0000~FFFFF

评分

参与人数 1鱼币 +6 收起 理由
小甲鱼 + 6

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-10-6 10:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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