如何将一个裸机引导起来呢?

hyqryq 2002-08-11 02:39:36
如何将一个裸机引导起来呢? 需要些什么步骤? 请讲详细一点, 有相关文档请给出链接好吗?
...全文
8 点赞 收藏 8
写回复
8 条回复
hyqryq 2002年08月17日
多谢各位!
回复 点赞
nicotinism 2002年08月17日
机器完成自检后,BIOS引导例程会将引导扇区的内容读入0000:7c00处,然后跳到0000:7c00处继续执行。
将你的程序写入引导扇区,整个机器就都是你的了。此时你只能调用BIOS中断,没有DOS中断可供调用。不过完成驻留是绰绰有余了。
回复 点赞
coderStone 2002年08月16日
上面文章是关于中文版Windows 98系统的硬盘主引导记录的汇编码情况;
希望对引导裸机理解有帮助。
回复 点赞
coderStone 2002年08月16日
------------------------------------------------------------------

0000:06E0 56 PUSH SI ;保存SI——注意,这次压栈并不构造磁盘地址包
0000:06E1 33F6 XOR SI,SI ;清零
0000:06E3 56 PUSH SI ;
0000:06E4 56 PUSH SI ;
0000:06E5 52 PUSH DX ;
0000:06E6 50 PUSH AX ;以上四条指令压栈的是扇区LBA号码*2
0000:06E7 06 PUSH ES ;压栈内存目标缓冲区首址段址
0000:06E8 53 PUSH BX ;压栈内存目标缓冲区首址偏移
0000:06E9 51 PUSH CX ;压栈所读扇区数
0000:06EA BE1000 MOV SI,0010 ;注意SI的高8位对应着磁盘地址包的保留字节,必须为0
0000:06ED 56 PUSH SI ;压栈磁盘地址包包长,执行完本条指令一个包已经构造完毕
0000:06EE 8BF4 MOV SI,SP ;规定磁盘地址包偏移指针,这时SP=7BEA
0000:06F0 50 PUSH AX ;保存AX
0000:06F1 52 PUSH DX ;保存DX
0000:06F2 B80042 MOV AX,4200 ;置扩展读功能号
0000:06F5 8A5624 MOV DL,[BP+24] ;取驱动器号,参照0000:0683
--------------------------------------------------------------------

0000:06F8 CD13 INT 13 ;执行扩展读操作
0000:06FA 5A POP DX ;
0000:06FB 58 POP AX ;
0000:06FC 8D6410 LEA SP,[SI+10] ;7BEA+10h=7BFA→SP(注意是取偏移而不是取单元内容)
0000:06FF 720A JB 070B ;扩展读不成功转
0000:0701 40 INC AX ;
0000:0702 7501 JNZ 0705 ;
0000:0704 42 INC DX ;AX加1溢出时(比如0FFFFh+1)DX才加1
0000:0705 80C702 ADD BH,02 ;调整BX,使偏移量增加512字节(刚好一扇区)
0000:0708 E2F7 LOOP 0701 ;0701~0708一段代码暂未明白其真实意图!
0000:070A F8 CLC ;
0000:070B 5E POP SI ;
0000:070C C3 RET
------------------------------------------------------------------
; 0000:0783~0000:0789:控制权移交
0000:0783 8BFC MOV DI,SP ;
0000:0785 1E PUSH DS ;
0000:0786 57 PUSH DI ;构造一个跳转地址
0000:0787 8BF5 MOV SI,BP ;
0000:0789 CB RETF ;交控制权给分区引导记录(0000:7C00)
----------------------------------------------------------------
互相学习,共同进步
回复 点赞
coderStone 2002年08月16日
romanmox(凌霜傲雪) 兄推荐的很好。读过以后很受启发;
我这儿也有一个,网站站长含笑,在此谢过。
引用如下,希望对大家有所帮助:

; 0000:7C00~0000:7C1A:初始化各个段寄存器、堆栈指针,最后将主引导记录在内存中搬家,腾出其所占内
; 存空间以供装入分区引导记录。
0000:7C00 33C0 XOR AX,AX ;AX寄存器清0
0000:7C02 8ED0 MOV SS,AX ;SS=0
0000:7C04 BC007C MOV SP,7C00 ;装填栈指针——SS:SP=0000:7C00
0000:7C07 FB STI ;开中断(装填栈指针时为避免硬件中断引起栈混乱应关中断)
0000:7C08 50 PUSH AX ;
0000:7C09 07 POP ES ;装填附加数据段寄存器ES=0
0000:7C0A 50 PUSH AX ;
0000:7C0B 1F POP DS ;装填数据段寄存器DS=0
0000:7C0C FC CLD ;规定其后的串操作为正向串操作
0000:7C0D BE1B7C MOV SI,7C1B ;源指针
0000:7C10 BF1B06 MOV DI,061B ;目的指针
0000:7C13 50 PUSH AX ;
0000:7C14 57 PUSH DI ;看看0000:7C1A——构造一个跳转
0000:7C15 B9E501 MOV CX,01E5 ;
0000:7C18 F3 REPZ ;
0000:7C19 A4 MOVSB ;0000:7C1B起始的CX字节传送至0000:061B起始的区域
0000:7C1A CB RETF ;跳转到0000:061B(这是一种技巧跳转)
;
------------------------------------------------------------
0000:061B BEBE07 MOV SI,07BE ;SI指向第一个分区表项,这时CX=0
0000:061E B104 MOV CL,04 ;分区表共四个表项
0000:0620 382C CMP [SI],CH ;
0000:0622 7C09 JL 062D ;大于等于80h转[注意JL指令:(SF xor OF)=1则转]
0000:0624 7515 JNZ 063B ;不为0则[SI]一定小于80h,只能转错误处理了!
0000:0626 83C610 ADD SI,+10 ;为零则检查下一表项
0000:0629 E2F5 LOOP 0620 ;检查下一表项
0000:062B CD18 INT 18 ;四表项的状态字节都为0,则系统只好调用INT 18h了!
-------------------------------------------------------------

0000:062D 8B14 MOV DX,[SI] ;为读分区引导记录做准备:磁头号→DH,驱动器号→DL
0000:062F 8BEE MOV BP,SI ;SI→BP,保存可引导分区表项的指针
;
0000:0631 83C610 ADD SI,+10 ;其余的分区表项还要检查检查的
0000:0634 49 DEC CX ;
0000:0635 7416 JZ 064D ;CX=0则检查顺利通过,转继续
0000:0637 382C CMP [SI],CH ;
0000:0639 74F6 JZ 0631 ;为零,是合法表项,再查下一表项
;
; 0000:063B~0000:064B:执行错误处理——报告错误信息后当机
0000:063B BE1007 MOV SI,0710 ;错误信息字符串偏移+1→SI
0000:063E 4E DEC SI ;SI-1→SI
0000:063F AC LODSB ;SI+1→SI
0000:0640 3C00 CMP AL,00 ;
0000:0642 74FA JZ 063E ;AL=0则表明一条错误信息显示完毕,系统陷入一个死循环
0000:0644 BB0700 MOV BX,0007 ;字符方式显示
0000:0647 B40E MOV AH,0E ;
0000:0649 CD10 INT 10 ;以写电传方式显示信息(只显示一个字符)
0000:064B EBF2 JMP 063F ;显示下一个字符,直到遇到提示信息结束为止
------------------------------------------------------------

0000:064D 894625 MOV [BP+25],AX ;BP=指向第一个可引导分区表项的指针,这时AX=0000h
;使用长度最短的指令将[BP+25]起始的两个单元清零
;这两个单元将被用来存放中间变量
0000:0650 96 XCHG SI,AX ;此时SI清零的最佳指令选择(仅1字节),将服务于0000:06B8
0000:0651 8A4604 MOV AL,[BP+04] ;取分区类型(本例是“06”喽——FAT16主DOS分区)
0000:0654 B406 MOV AH,06 ;为扩展INT 13h无法使用做好更改分区类型的准备
0000:0656 3C0E CMP AL,0E ;0Eh:需要用扩展INT 13h访问的FAT16主DOS分区
0000:0658 7411 JZ 066B ;0Eh类型的分区转066Bh
0000:065A B40B MOV AH,0B ;
0000:065C 3C0C CMP AL,0C ;0Ch:需要用扩展INT 13h访问的FAT32分区
0000:065E 7405 JZ 0665 ;0Ch类型的分区转0665h先行预处理
0000:0660 3AC4 CMP AL,AH ;0Bh:用传统INT 13h就可以访问的FAT32分区
0000:0662 752B JNZ 068F ;其他类型的分区转068Fh
;
; 0000:0664~0000:06A1:根据分区类型和分区表表项内容进行读取分区引导记录前的处理工作
0000:0664 40 INC AX ;★★★0Bh类型的分区由此开始处理,此条指令用意是清ZF位
0000:0665 C6462506 MOV BYTE PTR [BP+25],06 ;★★★0Ch类型的分区由此开始处理
;为什么取值06,一时没有自圆我说的解释,请耐心几天吧。
0000:0669 7524 JNZ 068F ;请注意上面指令对ZF位的影响:0Bh类型分区转,0Ch则不转
; 0000:066B~0000:068C这段代码仅当分区类型是0Ch、0Eh才有获得执行的机会
0000:066B BBAA55 MOV BX,55AA ;★★★0Eh类型的分区由此开始处理
0000:066E 50 PUSH AX ;
0000:066F B441 MOV AH,41 ;扩展INT 13h功能,检测BIOS是否已经支持扩展INT13h
0000:0671 CD13 INT 13 ;入口参数:BX=55AAh,DL=驱动器号,AH=41h
0000:0673 58 POP AX ;执行完恢复AX为060Eh
0000:0674 7216 JB 068C ;不支持则转
0000:0676 81FB55AA CMP BX,AA55 ;
0000:067A 7510 JNZ 068C ;扩展INT13h不可用也转
0000:067C F6C101 TEST CL,01 ;测试扩展盘访问是否被支持
0000:067F 740B JZ 068C ;不支持还转
-------------------------------------------------------

0000:0681 8AE0 MOV AH,AL ;分区类型→AH
0000:0683 885624 MOV [BP+24],DL ;保存驱动器号→[BP+24]
0000:0686 C706A106EB1E MOV WORD PTR [06A1],1EEB ;修改0000:06A1处代码为"JMP 06C1"
0000:068C 886604 MOV [BP+04],AH ;注意:如果扩展INT13h不能使用则A改分区类型为06,但如果
;扩展INT13h能使用,则仍保持原分区类型不变
0000:068F BF0A00 MOV DI,000A ;★★★其它类型分区由此开始处理。此条指令初始化计数器
0000:0692 B80102 MOV AX,0201 ;AH:读操作,AL:读取1个扇区的内容
0000:0695 8BDC MOV BX,SP ;SP=7C00→BX,指定分区引导记录装入内存的位置偏移
0000:0697 33C9 XOR CX,CX ;CX清零
0000:0699 83FF05 CMP DI,+05 ;注意5<DI≤A和DI≤5两者的区别:所读扇区不一样
0000:069C 7F03 JG 06A1 ;大于则转去读由分区表指定的分区引导扇区
0000:069E 8B4E25 MOV CX,[BP+25] ;小于则证明所读分区表指定的引导扇区无合法的引导记录,
;改按???

0000:06A4 CD13 INT 13 ;读分区引导记录到0000:7C00起始的区域
------------------------------------------------------------
;
0000:06A6 7229 JB 06D1 ;不成功转
0000:06A8 BE2D07 MOV SI,072D ;错误信息字符串偏移→SI
0000:06AB 813EFE7D55AA CMP WORD PTR [7DFE],AA55 ;分区引导记录合法吗?
0000:06B1 745A JZ 070D ;合法则转(这是主引导记录唯一的正常出口)

0000:06B3 83EF05 SUB DI,+05 ;不合法则为换读其他扇区做准备
0000:06B6 7FDA JG 0692 ;只有一次换读扇区的机会!
;
; 0000:06B8~0000:06BF:错误预处理
0000:06B8 85F6 TEST SI,SI ;测试SI值是否为0,其意义在于确定该显示哪条信息
0000:06BA 7583 JNZ 063F ;不为0则转错误处理,显示“Missing operating system”
0000:06BC BE1A07 MOV SI,071A ;错误信息字符串偏移→SI
0000:06BF EB8A JMP 064B ;转错误处理,显示“加载操作系统时出错”
------------------------------------------------------------------

0000:06C1 98 CBW ;转换字节AL为字AX,执行后,AX中是一次要读的扇区数
0000:06C2 91 XCHG CX,AX ;AX→CX,CX→AX,执行后,CX中是一次要读的扇区数
0000:06C3 52 PUSH DX ;
0000:06C4 99 CWD ;将字AX转换为双字→DX,AX
0000:06C5 034608 ADD AX,[BP+08] ;
0000:06C8 13560A ADC DX,[BP+0A] ;执行后,DX:AX=LBA绝对物理扇区号
0000:06CB E81200 CALL 06E0 ;调用
回复 点赞
romanmox 2002年08月15日
在本版精华区有个帖子
相信会对你有帮助

我看后受益匪浅
http://www.csdn.net/expert/topic/706/706607.xml?temp=.1210443

回复 点赞
zhangze 2002年08月11日
电脑开启后,加电自检完毕,会使用int19h/int 18h将磁盘0磁道1扇区(引导程序)的内容读到0:7c00的位置,并且跳转到该位置开始执行,所以,只要将磁盘的引导扇区的内容改写就可以引导操作系统了,需要注意的是:引导扇区只有512字节,所以必须在512字节内将必需的内容读入到内存中,中断调用只有bios中断可以使用,dos中断一概不可
回复 点赞
zhuzhu830829 2002年08月11日
你是要写操作系统吗?
回复 点赞
发动态
发帖子
汇编语言
创建于2007-08-27

1.9w+

社区成员

4.1w+

社区内容

汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区公告
暂无公告