我是无忧U盘区的版主,有问题请教:
看了我们做的测试,http://www.ultraiso.net/review/uboot.htm,对于最后的“ USB-CDROM光盘仿真模式,DOS启动后可以不占盘符,兼容性一般。”这句话不敢苟同,原因在于根本没有测试在里面。就广大网友所报告的实验结果来看,USBCDROM启动的兼容性要大于USBHDD和USBZIP,另外,我认为,CDROM启动是有最成熟的工业标准的,相对于USBHDD和ZIP格式启动应该更可靠。到底U+和USBCDROM启动,到底哪个成功率高,我有请原文作者做真正的测试,我可以提供相应帮助。
对于U+技术,MATRIX一直不做任何深入的介绍,只说是一种新技术,到底新到何处,避而不谈。U盘启动,成功与否是和BIOS及U盘都有直接关系的,因此,我不能完全相信一个U+技术就能大大提高启动兼容性。
直到现在,我还是无法想出U+到底先进在什么地方,难道是启动扇区更易于BIOS识别?
另外,就是这个USBHDD+和USBZIP+,和U盘量产成FIXED和REMOVABLE没有关系?一个REMOVABLE格式的U盘也可以使用USBHDD+来做吗?一个FIXED格式的U盘也可以使用USBZIP+来做吗?
无论是HDD+还是ZIP+,都是离不开HDD和ZIP这两种格式的,当然做为HDD,其CHS参数能被BIOS正确识别是对于启动是最重要的,但对于ZIP,标准的ZIP盘有100M和250M两种大小,但二者均有64磁头、32扇区,并且使用单一的分区4分区(http://www.pendrivelinux.com/200 ... p-on-older-systems/),请问我们的ZIP+做出的盘,H和S参数也是这两个吗?
以上问题,只是我想到的,抱歉我并没有使用U+技术来做启动U盘。
usbhdd+分析(修正2)
通过对Ultraiso便捷写入到U盘的usbhdd+代码分析,发现是个不同凡响的常驻内存mbr
1、判断自身存在的媒介
2、含有实模式32位指令,缩小了指令体积,但16位debug无法译码。
2、使用扩展int13接口访问磁盘,是U+技术关键
4、使用dos病毒常用的接管int 13中断的办法,让自己的一部分常驻内存,减少可用内存1k给自己使用
5、用or ah,40h将普通的int 13 2/3/4 读/写/验,变成了扩展int13接口的42/43/44,并进行数据协调,
使实模式下所有的读磁盘代码均能享受usbhdd+的加强访问磁盘的接口,直到系统进入保护模式(pe/linux).
感觉usbhdd+,就是在hdd mbr基础上加入了对新芯片新bios扩展int 13中断的支持,增强了兼容性,
并常驻内存一直加强实模式读盘能力。
seg000:7c00 cli ;关中断
seg000:7C01 xor ax, ax ;清寄存器
seg000:7C03 mov ds, ax ;ds,es,ss清0
seg000:7C05 mov es, ax
seg000:7C07 mov ss, ax
seg000:7C09 mov sp, 7C00h ;清段寄托器,准备复制去600,
seg000:7C0C sti ;为什么要去600?因为他要将分区代码放到7c00去执行
seg000:7C0D cld
seg000:7C0E mov si, sp
seg000:7C10 mov di, 600h
seg000:7C13 mov cx, 100h ;这段代码就是复制自身
seg000:7C16 rep movsw
seg000:7C18 jmp far ptr 0:6DCh 将bios把mbr放在7c00地点转个家到0600
seg000:7C18 ; -------- 就是复制自身过去
; ---------------------------------------------------------------------------
;7c1d之后是数据,从1d至33都是数据
610 BF 00 06 B9 00 01 F3 A5 EA DC 06 00 00 10 00 01 ??螗贶...
seg000:0620 00 00 7C 00 00 00 00 00 00 00 00 00 00 80 3F 00 ..|..........??.
seg000:0630 FF 00 08 0
;----------------------------------------------------------------------------
;int 13中断常驻服务子程序
;资料:DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
seg000:0634 push ds ;保存ds
;usbhdd+的技术核心,修改int 13中断以支持所以在实模式下
seg000:0635 push cs ;访问磁盘的能力
seg000:0636 pop ds ;cs入栈->ds
seg000:0637 cmp dl, ds:10h ;判断驱动器参数是否等于cs:10地址数据,即目前看是0610处的8f
;8f即移动hd
seg000:063B jz short loc_643 ;是则转643h继续
;-----------------------------------------------------------------------------
seg000:063D
;63d子程序是不在服务范围情况的处理,直接转保存的原bios int13放弃处理
seg000:063D loc_63D: ; CODE XREF: seg000:0670j
seg000:063D ; seg000:0675j
seg000:063D pop ds ;上面判断不成立,恢复ds
seg000:063D ; ---------------------------------------------------------------------------
seg000:063E jmp far ptr 0F000h:0E736h ;并则跳回保存的原int 13地址,是写中断向量之前保存的
; DATA XREF: seg000:073Ew
seg000:0643 ; ---------------------------------------------------------------------------
;比较ax是否=于0x54fb,不等于转64d服务子程序继续工作
;等于的话
seg000:0643
seg000:0643 loc_643: ; CODE XREF: seg000:063Bj
seg000:0643 cmp ax, 54FBh
seg000:0646 jnz short loc_64D
seg000:0648 mov ax, ds ;如果ax=54fb,则ds入ax,开中断,转66a,66a又转了6d2直接返回
seg000:064A sti ;而没有任何操作,ah=54这个功能号,在扩展int 13中没有查到
seg000:064B jmp short loc_66A ;应该是一个hdd+内部测试吧,可以测试出中断拦截是否到位,没有任何其他操作
seg000:064D ; ---------------------------------------------------------------------------
;功能08H
;功能描述:读取驱动器参数
;入口参数:AH=08H
;DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
;出口参数:CF=1——操作失败,AH=状态代码,参见功能号01H中的说明,否则, BL=01H — 360K
;=02H — 1.2M
;=03H — 720K
;=04H — 1.44M
seg000:064D
seg000:064D loc_64D: ; CODE XREF: seg000:0646j
seg000:064D cmp ah, 8 ;8号功能号,获取磁盘参数加强
seg000:0650 jnz short loc_66D ;不为8则转66d再判断
seg000:0652 call sub_6D6 ;调用去原int 13的子程序
seg000:0655 mov dh, ds:13h ;对返回结果进行处理[13]=B9
seg000:0659 dec dh
seg000:065B mov cx, ds:15h ;[15]=00 01
seg000:065F xchg cl, ch
seg000:0661 shl cl, 6
seg000:0664 or cl, ds:11h
seg000:0668 xor ax, ax
seg000:066A
seg000:066A loc_66A: ; CODE XREF: seg000:064Bj
seg000:066A clc
seg000:066B jmp short loc_6D2 ;转6da返回
seg000:066D ; ---------------------------------------------------------------------------
;功能02H
;功能描述:读扇区/入口参数:AH=02H
;AL=扇区数
;CH=柱面
;CL=扇区
;DH=磁头
;DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
;ES:BX=缓冲区的地址
;出口参数:CF=0——操作成功,AH=00H,AL=传输的扇区数,否则,AH=状态代码,参见功能号01H中的说明
;功能描述:写扇区
;入口参数:AH=03H
;AL=扇区数
;CH=柱面
;CL=扇区
;DH=磁头
;DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
ES:BX=缓冲区的地址
出口参数:CF=0——操作成功,AH=00H,AL=传输的扇区数,否则,AH=状态代码,参见功能号01H中的说明
;功能描述:检验扇区/入口参数:AH=04H
;AL=扇区数
;CH=柱面
;CL=扇区
;DH=磁头
;DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
;ES:BX=缓冲区的地址
;出口参数:CF=0——操作成功,AH=00H,AL=被检验的扇区数,否则,AH=状态代码,参见功能号01H中的说明
seg000:066D
seg000:066D loc_66D: ; CODE XREF: seg000:0650j
seg000:066D cmp ah, 2 ;2号功能读扇区功能加强处理子程序
seg000:0670 jb short loc_63D ;小于2不在范围,转63d call原int 13
seg000:0672 cmp ah, 4 ;4号功能检测扇区功能加强处理子程序
seg000:0675 ja short loc_63D ;大于4不在范围,转63d call原int 13
seg000:0677 pusha
seg000:0678 or ah, 40h ;高位填充,2会变成42,4会变44
seg000:067B push ax ;原来是将普通的int 13 2/3/4 读/写/验,变成了扩展int13接口的42/43/44
seg000:067C mov si, 0 ;正好吻合,真是挺高的
seg000:067F mov word ptr [si], 10h ;int 13扩展中断的调用方式是不同,下面进行接口协调
seg000:0683 xor ah, ah
seg000:0685 mov [si+2], ax
seg000:0688 mov [si+4], bx
seg000:068B mov word ptr [si+6], es
seg000:068E xor eax, eax
seg000:0691 mov [si+0Ch], eax
seg000:0695 mov al, dh
seg000:0697 mul byte ptr ds:11h
seg000:069B mov bh, cl
seg000:069D mov bl, ch
seg000:069F shr bh, 6
seg000:06A2 and cx, 3Fh
seg000:06A6 add ax, cx
seg000:06A8 dec ax
seg000:06A9 mov di, ax
seg000:06AB mov ax, ds:13h
seg000:06AE mul word ptr ds:11h
seg000:06B2 mul bx
seg000:06B4 add ax, di
seg000:06B6 adc dx, 0
seg000:06BA mov [si+8], ax
seg000:06BD mov [si+0Ah], dx
seg000:06C0 pop ax
seg000:06C1 xor al, al
seg000:06C3 mov dl, ds:10h
seg000:06C7 call sub_6D6 ;调用扩展int 13
seg000:06CA mov ds:3, ah
seg000:06CE popa ;恢复环境
seg000:06CF mov ax, ds:2
seg000:06D2
seg000:06D2 loc_6D2: ; CODE XREF: seg000:066Bj
seg000:06D2 pop ds
seg000:06D3 retf 2
seg000:06D6
seg000:06D6 ; =============== S U B R O U T I N E =======================================
seg000:06D6
seg000:06D6
seg000:06D6 sub_6D6 proc near ; CODE XREF: seg000:0652p
seg000:06D6 ; seg000:06C7p
seg000:06D6 pushf
seg000:06D7 call dword ptr ds:22h ;调用修改的jmp 原int13指令中的dword地址.61d+22=63f,32位dword.
;就是FF1E2200 CALL FAR [0022](debug)
seg000:06DB retn ;ida把所有没有指定段寄托器的内存变量,都自动加上默认的ds,内存地址
seg000:06DB sub_6D6 endp ;的形式,是没有括号的
seg000:06DB
; ---------------------------------------------------------------------------
;-------------------------------------------------------------------------------
;6dc处继续执行初始化工作,这里是主程序
seg000:06DC
seg000:06DC loc_6DC: ; CODE XREF: seg000:0618J
seg000:06DC cmp dl, 8Fh ; '? ;判断bios传来的参数,以断定自己在什么存储媒介上
seg000:06DF jg short loc_6E5 ;这是其他的老mbr没有的
seg000:06E1 mov ds:byte_62D, dl ;如果不是8f将数据保存的62d
seg000:06E5
seg000:06E5 loc_6E5: ; CODE XREF: seg000:06DFj
--------------------------------------------------------------------------------
seg000:06E5 mov si, 787h ;
seg000:06E8 call sub_778 ;用bios int10显示boot starting等,就是hdd+的启动显示标志
seg000:06EB mov si, 7BEh ;si指向本扇区一起读出的分区表,偏移是标准的600+1be
seg000:06EE xor ax, ax ;ax清0当活动分区计数器
seg000:06F0 mov cx, 4 ;只读4次,一个主分区表只有4格
seg000:06F3
seg000:06F3 loc_6F3: ; CODE XREF: seg000:06FFj
seg000:06F3 test byte ptr [si], 80h ;80是正确的分区的标制
seg000:06F6 jz short loc_6FB ;找到80的活动分区转6fb
seg000:06F8 inc ax ;找一个活动分区,计数器加1
seg000:06F9 mov bp, si ;7be入bp
seg000:06FB
seg000:06FB loc_6FB: ; CODE XREF: seg000:06F6j
seg000:06FB add si, 10h ;一个分区表项16字节,指向下一个
seg000:06FF loop loc_6F3 ;循环再用80标志检测分区项
seg000:0701 dec ax ;ax-1,如果不为0就是有2个活动分区或者没有活动分区,拉倒了,重启
seg000:0702 jz short loc_706 ;搜索分区表后,只有一个正确分区转706继续工作,否则int 18停活
seg000:0704 int 18h ; TRANSFER TO ROM BASIC
seg000:0704 ; causes transfer to ROM-based BASIC (IBM-PC)
seg000:0704 ; often reboots a compatible; often has no effect at all
seg000:0706 ;转而执行INT 18H的BOOT异常执行中断程序(参考其他)
seg000:0706 loc_706: ; CODE XREF: seg000:0702j
seg000:0706 mov di, 5 ;di当读取次数计数器
seg000:0709
seg000:0709 loc_709: ; CODE XREF: seg000:072Fj
seg000:0709 mov si, 61Dh
seg000:070C mov word ptr [si+2], 1
seg000:0711 mov eax, [bp+8]
seg000:0715 mov [si+8], eax
seg000:0719 mov ax, 4200h ;使用了int 13扩展功能的int 13 ah=42读
seg000:071C mov dl, ds:byte_62D
seg000:0720 int 13h ;DISK - 读出活动分区的第1扇区
seg000:0722 jnb short loc_731 ;读出成功转分区引导扇区的代码,进行检查,准备放出ip权
seg000:0724 dec di ;每读一次分区引导区,di-1,只尝试5次
seg000:0725 jz short loc_770 ;di为0,而没有成功转走,5次读失败,就是引导失败,转770死循环
seg000:0727 xor ah, ah ;还在5次以内,复位磁盘,准备转709继续尝试
seg000:0729 mov dl, ds:byte_62D
seg000:072D int 13h ; DISK - RESET DISK SYSTEM
seg000:072D ; DL = drive (if bit 7 is set both hard disks and floppy disks reset)
seg000:072F jmp short loc_709 ;重读
seg000:0731 ; ---------------------------------------------------------------------------
seg000:0731 ;读出分区引导代码后
seg000:0731 loc_731: ; CODE XREF: seg000:0722j
seg000:0731 mov ax, ds:7DFEh ;分区引导记录已读出,分析是否正常
seg000:0734 cmp ax, 0AA55h ;没有aa55标记是数据分区,拉倒
seg000:0737 jnz short loc_770 ;不正确转770死循环,这2处重大失败都没有走int 18
;----------------------------------------------------------------------------------------------
;这一段是保存原中断向量,并修改跳回指令
seg000:0739 cli
seg000:073A mov eax, ds:4Ch ;32位取中断向量表int 13,汗了,原来是这样搞的
seg000:073E mov ds:dword_63F, eax ;保存在63f
;这是一次代码自修改,63f为seg000:063E jmp far ptr 0F000h:0E736h
;直接修改了jmp跳转地址
;--------------------------------------------------------------------------------------------
;这一段是将自己的一部分常驻内存顶端,并减少内存1k,大小为120字节的代码和数据
seg000:0742 mov si, 413h ;si=413,此处存放最大的内存0000:0413
seg000:0745 mov ax, [si] ;[413]内容入ax
seg000:0747 dec ax ;ax-1,为自己弄了1k空间
seg000:0748 mov [si], ax ;送回[413],等于把[413]-1,dos下内存少了1K
seg000:074A shl ax, 6 ;将ax里面的412移到高位,形成段地址
seg000:074D mov es, ax ;送到段寄存器es,应该=0x
seg000:074F xor di, di ;di清零
seg000:0751 mov si, 61Dh ;si指向61d,又准备传送自身了
seg000:0754 mov cx, 60h ; '`' ;传送长度为60*2=120字节
seg000:0757 cld
seg000:0758 rep movsw ;开始传送了,将61d-6dd传送到00ad:0000
seg000:075A mov word ptr ds:4Ch, 17h ;写中断向量表 int13,加强分区引导代码的读功能
;双字节写入的,是0017
seg000:0760 mov ds:4Eh, ax ;61d传去的,但开头是数据,要以634为开头,
;中断向量表写的低位是17,正是现在的634中断服务程序,挺精巧的计算
seg000:0763 sti ;恢复dl,bios专用参数
seg000:0764 mov dl, ds:byte_62D ;将62d保存的媒介信息继续用dl传给分区引导代码
seg000:0768 mov si, bp
seg000:076A cli
seg000:076B jmp far ptr 0:7C00h ;经检查正常后,向读到7c00的分区引导代码放ip权。
seg000:0770 ; ---------------------------------------------------------------------------
seg000:0770 ;引导失败走这里显示 .Boot faile
seg000:0770 loc_770: ; CODE XREF: seg000:0725j
seg000:0770 ; seg000:0737j
seg000:0770 mov si, 7AAh
seg000:0773 call sub_778 ;用778显示专用子程序将7aa的错误信息显示出来
seg000:0776
seg000:0776 loc_776: ; CODE XREF: seg000:loc_776j
seg000:0776 jmp short loc_776 ;从这里失败以后就是死循环了,不断运行这条指令
seg000:0778
seg000:0778 ; =============== S U B R O U T I N E =======================================
seg000:0778; 778子程序是调用int10显示文本
seg000:0778
seg000:0778 sub_778 proc near ; CODE XREF: seg000:06E8p
seg000:0778 ; seg000:0773p ...
seg000:0778 lodsb
seg000:0779 and al, al
seg000:077B jz short locret_786 ;这个转移应该是不成立的,转到数据上肯定死机
seg000:077D mov ah, 0Eh ;不转移的话正常显示文本
seg000:077F mov bx, 7
seg000:0782 int 10h ; - VIDEO - WRITE CHARACTER AND ADVANCE CURSOR (TTY WRITE)
seg000:0782 ; AL = character, BH = display page (alpha modes)
seg000:0782 ; BL = foreground color (graphics modes)
seg000:0784 jmp short sub_778
seg000:0786 ; ---------------------------------------------------------------------------
seg000:0786
seg000:0786 locret_786: ; CODE XREF: sub_778+3j
seg000:0786 retn
seg000:0786 sub_778 endp
seg000:0786
seg000:0786 ; ---------------------------
start boot form usb ...
Start boo
seg000:0790 74 69 6E 67 20 66 72 6F 6D 20 55 53 42 20 64 65 ting from USB de
seg000:07A0 76 69 63 65 2E 2E 2E 0D 0A 00 42 6F 6F 74 20 66 vice
.Boot f
seg000:07B0 61 69 6C 65 64 00 00 00 01 8B 09 00 00 00 00 00 ailed
分区表
80 01 ..............?
seg000:07F0 01 00 0E FE 3F 07 3F 00 00 00 C1 F7 01 00
今天没事又修正了下,第2次修正,排版总是不齐的,不管了
victor888,我们讨论任何东西,不同的人有不同的见解。我们不可以因为我们的见解与别人的不同,而对别人造成伤害。我们不要打击别人的劳动热情和积极性。所以,在我们没有确凿的证据之前,我们不能说我们比谁谁谁强。况且我们这里讨论的 U+,似乎没有几个人真正深入了解。如果一个人很了解 GRUB,而去与他不了解的 U+ 相比,不由自主地要带上有色眼镜,这样就不能保证适当的公平性了。
因此,我们能够讨论的,只能是技术本身。
根据以上某位朋友的研究结果,U+ 使用的是把 int13 的 2、3 等功能延伸到 42h、43h 的做法,并不涉及 USB 驱动的内置。从技术的角度,我觉得这样做并没有什么实质性的改进。这样的做法,其本质是把没有 EBIOS 支持的 int13 改造成有 EBIOS 的 int13,改造的根本依据是原来的 int13。也就是说,原来的 int13 只有 CHS 的访问能力,不可能访问超过 8.4G 的扇区数据。改造后的 EBIOS 仍然不可能超越 8.4G 的极限,因为这里的 EBIOS 所调用的正是原来的 BIOS int13。那么这样一来,其改造的实际意义就在于,它能给 DOS 等实模式程序提供 EBIOS 接口。恕我冒昧,好像这也是这一改造的仅有的好处,我不能发现这样的改造还有什么别的好处了。
好了,接下来我们看看如果为实模式的程序提供 EBIOS,有什么好处。
1. 这个 EBIOS 并不能提高磁盘扇区的访问数量,也即,仍然有 8.4G 极限(见上面的分析),从这一角度来讲,没有见到任何好处。
2. DOS 是很古老的产物,没有 EBIOS 它照样运行很好。从这一角度讲,也么有见到好处。
3. 有没有只支持 EBIOS 而不支持 BIOS 的实模式软件呢?没有的。所有支持 EBIOS 的软件都同时支持常规的 BIOS,这是由于历史的原因造成的,BIOS 是古老的标准,没有哪个软件可以跳过 BIOS 而仅仅去支持 EBIOS 的。所以,从这一角度来讲,也没有见到好处。
4. 有没有这样的软件,即,当只有 BIOS 时,其运行不太好,而假若有 EBIOS 接口,其运行更加良好呢?有的,grub4dos 就是一个例子(还有其他软件如 freeDOS 等)。但是,grub4dos 却不需要来自第三方的 EBIOS 接口,而真正需要的是原始的主板生产者所提供的 EBIOS 接口。为什么呢?因为下面将要谈到,从 CHS(即普通 BIOS) 到 LBA(即EBIOS)的转换,是不容易做好的!如果做坏了,反而会引起 grub4dos 等软件的死机。
为什么从 CHS 到 LBA 的变换就这么难做呢?这难道不是一件很容易的事情吗?CHS 到 LBA,或者反过来从 LBA 到 CHS,难道不是简单的数学运算吗?呵呵,数学运算当然简单,但这件事情就不简单了。难就难在不少的 BIOS 都不能提供一个正确的 Cmax, Hmax, Smax 值,而转换 CHS 三维地址到 LBA 线性地址的前提条件就是 Cmax, Hmax, Smax 是已知的。如果这三个值是不可用的,那么转换出来的结果可想而知,将是灾难性的。前面说了,依靠常规的手段如 int13 的 8 号功能以及 int13 的 48h 功能,可能都不能得到正确的 Cmax, Hmax, Smax 的值。因此,转换之前需要一个更复杂的探测过程,来测试 BIOS 实际使用的 Cmax, Hmax, Smax 的值。这就是新版的 grub4dos 里面的自动适应 BIOS 磁盘几何参数功能。这个探测本身就需要一个扇区的代码,很大的。如果再加上仿真代码以及 MBR 的常规引导代码,其代码量会增大到几个扇区,很难在两个扇区之内完成。前面有人说了,U+ 的代码只有两个扇区,那么我就可以推测,其中不含 CHS 的探测适应代码了。
如果不经 CHS 探测就转换到 EBIOS 的 LBA 地址,那么这个转换本身就是不可靠的。如果把这个不可靠的 EBIOS 当作 可靠的 EBIOS 提供给 grub4dos 等实模式软件,那么 grub4dos 等实模式软件将会遇到灾难(灾难是传递的,就像多米诺骨牌,只要领头的一个倒下了,后面的全都要倒下)。而假若没有遭到这个灾难性的 EBIOS 的欺骗,grub4dos 还有可能利用自身的 CHS 探测适应功能正常运作下去,其他软件如 FreeDOS 等也可能会利用常规的 BIOS 运作下去(当然如果没有可靠的 CHS 探测适应功能,那么遭到死机的可能性仍然很大)。
从这个长篇分析可见,上述第 4 条也没能见到有任何好处。
综上所述,简单为 int13 的 2,3 功能附加了 42h,43h 的扩展,这样的做法,以我的眼光来看(一管之见),没有任何意义。这里只是讨论技术,我只是从技术的角度,表明我的观点。
但是如果撇开技术,我仍然对 U+ 的开发和努力表示支持和敬佩,大家都是在探索嘛,目的都是为了给用户提供更好用的软件,所以大家都是一家人。我们在开发 grub4dos 的过程中,不也一样曾经犯过这样那样的错误吗?我们可以改进、可以发展,那么 U+ 也可以改进和发展。技术的前进是无止境的。
欢迎光临 EZB 论坛 (http://ultraiso.net/ezbbbs/) | Powered by Discuz! 6.1.0 |