bin2yx 发表于 2017-7-8 16:23:58

和CPU说话05

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==[:336h] 查证后 al=0
        jz c                        ;好像是为0跳转
       
        call twocall        ;******这里应该暂时不用管 因为 还没有到这里******
       
       
c:                                        ;第一CALL   al===0后跳到这里 等于前边什么都没做
                                        ; 在 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,        ;bx=ax这是什么意思?好像这个内存值是ax的值
        shr bx,0x8                        ;bl=ah假如是ax值 ,那么这里就是取aH的值,int13入口 哈哈
        mov ,bl                ;入口值ah存入
        mov si,        ;si=ax
        and si,0xff                        ;si低位清零
        mov al,                ;al=dl 但是这里不太清楚是高位还是低位***???应该是低位
        mov ah,        ;ah=cl
        mov cl,        ;cl=al
        mov dx,        ;dx=cx
        shr dx,0x8                        ;dl=ch
        mov ,dx        ;cx存入
        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,        ;dl=cl(入口值,起始扇区号)
        mov ,dl                ;cl(入口值,起始扇区号)存入
        mov ,ah                ;cl(入口值,起始扇区号)存入
        mov dx,        ;dx=dx(入口值,
        shr dx,0x8                        ;dl=dh(入口值,磁头号)
        mov ,dl                ;dh(入口值,磁头号)存入
        mov ,al                ;dl(入口值,驱动器号)存入
        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,        ;高位扩展为0 即 ax=0000+dl(dl为入口值)
        call gcall                        ;word 0x3264应该快接近真相了吧
        test ax,ax                        ;ax=1或者0,这是从71h端口读出的一个数值处理后得到
        jz word 0x3500                ;为0时跳,***暂时先不理会***
        ;假设ax=1,执行下列命令
        movzx dx,        ;高位扩展为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,                ;介质是否已知,都会跳到这里,不同的是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,                ;例行放屁
        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,                ;这是在脱裤子放屁吗,lea指令将一个近地址指针写入到指定的寄存器
        ;这里即将ss:的地址赋值给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=0xeax=0x40
                                        ;bios数据查询程序,这里查字 单元
        push bx                       
        push bp                       
        mov bp,sp                ;等于栈指针此时的数值,6 这之前push了8个寄存器,最后一个是bp
        mov bx,dx
        mov es,ax
        mov ax,        ;ax= 这里是BIOS数据区的一个数值,不知道是什么
        pop bp
        pop bx
        ret
onecalltwo:                        ;此时dx=0x366 ax==9fc0
                                        ;第二次dx=0x3e ax=0x40
                                        ;bios数据查询程序,这里查字节 单元
        push bx
        push bp
        mov bp,sp
        mov bx,dx
        mov es,ax                ;es==9fc0       
        mov al,        ;al===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
页: [1]
查看完整版本: 和CPU说话05