版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
《x86汇编语⾔:从实模式到保护模式》配套代码清单c05_mbr.asm;代码清单5-1;⽂件名:c05_mbr.asm;⽂件说明:硬盘主引导扇区代码;创建⽇期:2011-3-3121:15movax,0xb800;指向⽂本模式的显⽰缓冲区moves,ax;以下显⽰字符串"Labeloffset:"movbyte[es:0x00],'L'movbyte[es:0x01],0x07movbyte[es:0x02],'a'movbyte[es:0x03],0x07movbyte[es:0x04],'b'movbyte[es:0x05],0x07movbyte[es:0x06],'e'movbyte[es:0x07],0x07movbyte[es:0x08],'l'movbyte[es:0x09],0x07movbyte[es:0x0a],''movbyte[es:0x0b],0x07movbyte[es:0x0c],"o"movbyte[es:0x0d],0x07movbyte[es:0x0e],'f'movbyte[es:0x0f],0x07movbyte[es:0x10],'f'movbyte[es:0x11],0x07movbyte[es:0x12],'s'movbyte[es:0x13],0x07movbyte[es:0x14],'e'movbyte[es:0x15],0x07movbyte[es:0x16],'t'movbyte[es:0x17],0x07movbyte[es:0x18],':'movbyte[es:0x19],0x07movax,number;取得标号number的偏移地址movbx,10;设置数据段的基地址movcx,csmovds,cx;求个位上的数字movdx,0divbxmov[0x7c00+number+0x00],dl;保存个位上的数字;求⼗位上的数字xordx,dxdivbxmov[0x7c00+number+0x01],dl;保存⼗位上的数字;求百位上的数字xordx,dxdivbxmov[0x7c00+number+0x02],dl;保存百位上的数字;求千位上的数字xordx,dxdivbxdivbxmov[0x7c00+number+0x03],dl;保存千位上的数字;求万位上的数字xordx,dxdivbxmov[0x7c00+number+0x04],dl;保存万位上的数字;以下⽤⼗进制显⽰标号的偏移地址moval,[0x7c00+number+0x04]addal,0x30mov[es:0x1a],almovbyte[es:0x1b],0x04moval,[0x7c00+number+0x03]addal,0x30mov[es:0x1c],almovbyte[es:0x1d],0x04moval,[0x7c00+number+0x02]addal,0x30mov[es:0x1e],almovbyte[es:0x1f],0x04moval,[0x7c00+number+0x01]addal,0x30mov[es:0x20],almovbyte[es:0x21],0x04moval,[0x7c00+number+0x00]addal,0x30mov[es:0x22],almovbyte[es:0x23],0x04movbyte[es:0x24],'D'movbyte[es:0x25],0x07infi:jmpnearinfinumberdb0,0,0,0,0times203db0db0x55,0xaa;⽆限循环c06_mbr.asmjmpnearstartmytextdb'L',0x07,'a',0x07,'b',0x07,'e',0x07,'l',0x07,'',0x07,'o',0x07,\'f',0x07,'f',0x07,'s',0x07,'e',0x07,'t',0x07,':',0x07numberdb0,0,0,0,0start:movax,0x07c0;设置数据段基地址movds,axmovax,0xb800;设置附加段基地址moves,ax;这⾥附加段指向显存位置,存放在es寄存器中;ds寄存器⼀般保存数据段基地址cld;将⽅向标志位DF清零,以指⽰传送是负⽅向的,与此相对应的指令是stdmovsi,mytext;movsw指令原始数据串需要存放在ds:si位置,⽬的地址为es:di,因为ds⽬前指⽰的是当前代码段基地址地址,因此只要把偏移mytext存⼊si寄存器即可movdi,0;当前es指⽰显存起始位置,因此只要把偏移0存⼊di即可movcx,(number-mytext)/2;实际上等于13,cx作为计数器,每进⾏⼀次rep指令cx-1repmovsw;⼀次传送⼀个字(两个字节);得到标号所代表的偏移地址movax,number;此代码⽬的旨在显⽰number的偏移地址;计算各个数位movbx,ax;bx指向当前number偏移地址movcx,5;循环次数movsi,10;除数digit:xordx,dx;dx(被除数⾼16位)清零divsi;除法mov[bx],dl;保存数位;为什么这⾥不⽤加0x7c00了?incbx;bx⾃加1,指向下⼀个内存单元,number⼀共定义了5个字节内存单元loopdigit;显⽰各个数位movbx,numbermovsi,4show:moval,[bx+si];从后往前显⽰addal,0x30movah,0x04mov[es:di],axadddi,2decsijnsshow;上⼀条指令符号位为SF=0(结果为⾮负)时跳转movword[es:di],0x0744jmpnear$;⽆限循环times510-($-$$)db0;512字节减去之后两个db指令=510字节,$当前指令偏移,$$当前代码段起始位置,填充字节0(db0)db0x55,0xaac07_mbr.asmjmpnearstartmessagedb'1+2+3+...+100='start:movax,0x7c0;设置数据段的段基地址movds,axmovax,0xb800;设置附加段基址到显⽰缓冲区moves,ax;以下显⽰字符串movsi,messagemovdi,0movcx,start-message@g:moval,[si];因为这是硬盘主引导扇区代码,因此被加载到0x7c00,[si]=[ds:si],就是相对于代码段开头的相对偏移,这个相对偏移就是标签message的值mov[es:di],alincdi;di⽤做显存段地址的相对偏移,字符内容信息放在低⼀个字节movbyte[es:di],0x07incdi;字符显⽰信息放在⾼⼀个字节incsi;si⽤作寻址字符串相对偏移loop@g;以下计算1到100的和xorax,ax;清空ax寄存器,存放结果movcx,1@f:addax,cxinccx;cx做累加器cmpcx,100jle@f;⼩于等于时跳转;以下计算累加和的每个数位xorcx,cxmovss,cx;设置堆栈段的段基地址movsp,cx;堆栈段指针和段基址都在0x0000处,堆栈段从⾼地址向低地址⽣长movbx,10xorcx,cx@d:inccx;压栈中⽤cx记录⼀共压⼊栈元素个数,以便之后出栈时能及时停⽌popxordx,dx;被除数[dx:ax]divbx;除数bxordl,0x30;余数在dx中,但是余数最多到9,因此在dl中就够了,加0x30得到ASCII码pushdx;dx中只有dl有意义,但是压栈的单位必须是字(两个字节)cmpax,0jne@d;循环跳出时,结果5050每⼀位被放在栈中;以下显⽰各个数位@a:popdx;出栈,栈顶元素是千位,百位,⼗位,个位mov[es:di],dlincdimovbyte[es:di],0x07incdiloop@ajmpnear$8086寻址⽅式总结:1.寄存器寻址:movax,cx2.⽴即寻址:addbx,0xf000(⽬的操作数⽴即数寻址,源操作数寄存器寻址)3.直接寻址:movax,[0x5c0f]4.基址寻址:利⽤基址寄存器bx/bp中的值作为偏移地址,其中bx默认段寄存器为ds(数据段),bp默认段寄存器为ss(堆栈段)。堆栈段指针寄存器为sp,不要混淆。如:movdx,[bp-2]5.变址寻址:利⽤变址寄存器si/di中的值作为偏移地址,默认段寄存器为ds如:mov[si+0x100],al6.基址变址寻址:利⽤基址寄存器bx/bp和变址寄存器si/di相加作为偏移地址如:addword[bx+di],0x3000加载程序源程序c08_mbr.asm;代码清单8-1;⽂件名:c08_mbr.asm;⽂件说明:硬盘主引导扇区代码(加载程序);创建⽇期:2011-5-518:17app_lba_startequ100;声明常数(⽤户程序起始逻辑扇区号);常数的声明不会占⽤汇编地址SECTIONmbralign=16vstart=0x7c00;设置堆栈段和栈指针movax,0movss,axmovsp,axmovax,[cs:phy_base];计算⽤于加载⽤户程序的逻辑段地址movdx,[cs:phy_base+0x02]movbx,16divbxmovds,axmoves,ax;令DS和ES指向该段以进⾏操作;以下读取程序的起始部分xordi,dimovsi,app_lba_start;程序在硬盘上的起始逻辑扇区号;加载到DS:0x0000处xorbx,bxcallread_hard_disk_0;以下判断整个程序有多⼤movdx,[2];曾经把dx写成了ds,花了⼆⼗分钟排错movax,[0]movbx,512;512字节每扇区divbxcmpdx,0jnz@1;未除尽,因此结果⽐实际扇区数少1decax;已经读了⼀个扇区,扇区总数减1@1:cmpax,0;考虑实际长度⼩于等于512个字节的情况jzdirect;读取剩余的扇区pushdsmovcx,ax@2:;以下要⽤到并改变DS寄存器;循环次数(剩余扇区数)movax,dsaddax,0x20;得到下⼀个以512字节为边界的段地址movds,axxorbx,bx;每次读时,偏移地址始终为0x0000;每次读时,偏移地址始终为0x0000xorbx,bxincsi;下⼀个逻辑扇区callread_hard_disk_0loop@2;循环读,直到读完整个功能程序popds;恢复数据段基址到⽤户程序头部段;计算⼊⼝点代码段基址direct:movdx,[0x08]movax,[0x06]callcalc_segment_basemov[0x06],ax;回填修正后的⼊⼝点代码段基址;开始处理段重定位表movcx,[0x0a];需要重定位的项⽬数量movbx,0x0c;重定位表⾸地址realloc:movdx,[bx+0x02];32位地址的⾼16位movax,[bx]callcalc_segment_basemov[bx],ax;回填段的基址addbx,4;下⼀个重定位项(每项占4个字节)jmpfar[0x04];转移到⽤户程序looprealloc;-------------------------------------------------------------------------------read_hard_disk_0:;从硬盘读取⼀个逻辑扇区;输⼊:DI:SI=起始逻辑扇区号;DS:BX=⽬标缓冲区地址pushaxpushbxpushcxpushdxmovdx,0x1f2moval,1outdx,alincdx;读取的扇区数;0x1f3movax,sioutdx,alincdx;LBA地址7~0;0x1f4moval,ahoutdx,alincdx;LBA地址15~8;0x1f5movax,dioutdx,alincdx;LBA地址23~16;0x1f6moval,0xe0;LBA28模式,主盘oral,ah;LBA地址27~24outdx,alincdx;0x1f7moval,0x20;读命令outdx,al.waits:inal,dxcmpal,0x08jnz.waits;不忙,且硬盘已准备好数据传输movcx,256;总共要读取的字数movdx,0x1f0.readw:inax,dxmov[bx],axaddbx,2loop.readwpopdxpopcxpopbxpopaxret;-------------------------------------------------------------------------------calc_segment_base:;计算16位段地址;输⼊:DX:AX=32位物理地址;返回:AX=16位段基地址pushdxaddax,[cs:phy_base]adcdx,[cs:phy_base+0x02]shrax,4rordx,4anddx,0xf000orax,dxpopdxret;-------------------------------------------------------------------------------phy_basedd0x10000;⽤户程序被加载的物理起始地址times510-($-$$)db0db0x55,0xaa⽤户程序编译源程序c08.asm;代码清单8-2;⽂件名:c08.asm;⽂件说明:⽤户程序;创建⽇期:2011-5-518:17;===============================================================================SECTIONheadervstart=0;定义⽤户程序头部段program_lengthddprogram_end;程序总长度[0x00];⽤户程序⼊⼝点code_entrydwstart;偏移地址[0x04]ddsection.code_1.start;段地址[0x06]realloc_tbl_lendw(header_end-code_1_segment)/4;段重定位表项个数[0x0a];段重定位表code_1_segmentddsection.code_1.start;[0x0c]code_2_segmentddsection.code_2.start;[0x10]data_1_segmentddsection.data_1.start;[0x14]data_2_segmentddsection.data_2.start;[0x18]header_end:;===============================================================================SECTIONcode_1align=16vstart=0;定义代码段1(16字节对齐)put_string:;显⽰串(0结尾)。;输⼊:DS:BX=串地址movcl,[bx]orcl,cljz.exit;cl=0?;是的,返回主程序callput_charincbx;下⼀个字符jmpput_string.exit:ret;-------------------------------------------------------------------------------put_char:;显⽰⼀个字符;输⼊:cl=字符asciipushaxpushbxpushcxpushdxpushdspushes;以下取当前光标位置movdx,0x3d4moval,0x0eoutdx,almovdx,0x3d5inal,dx;⾼8位movah,almovdx,0x3d4moval,0x0foutdx,almovdx,0x3d5inal,dx;低8位movbx,ax;BX=代表光标位置的16位数cmpcl,0x0d;回车符?jnz.put_0a;不是。看看是不是换⾏等字符movax,bx;此句略显多余,但去掉后还得改书,⿇烦movbl,80divblmulblmovbx,axjmp.set_cursor.put_0a:cmpcl,0x0a;换⾏符?jnz.put_otheraddbx,80;不是,那就正常显⽰字符jmp.roll_screen.put_other:;正常显⽰字符movax,0xb800moves,axshlbx,1mov[es:bx],cl;以下将光标位置推进⼀个字符.roll_screen:cmpbx,2000;光标超出屏幕?滚屏jl.set_cursormovax,0xb800movds,axmoves,axcldmovsi,0xa0movdi,0x00movcx,1920repmovswmovbx,3840;清除屏幕最底⼀⾏movcx,80.cls:movword[es:bx],0x0720addbx,2loop.clsmovbx,1920.set_cursor:movdx,0x3d4moval,0x0eoutdx,almovdx,0x3d5moval,bhoutdx,almovdx,0x3d4moval,0x0foutdx,almovdx,0x3d5moval,bloutdx,alpopespopdspopdxpopcxpopbxpopaxret;-------------------------------------------------------------------------------start:;初始执⾏时,DS和ES指向⽤户程序头部段movax,[stack_segment];设置到⽤户程序⾃⼰的堆栈movss,axmovsp,stack_endmovax,[data_1_segment];设置到⽤户程序⾃⼰的数据段movds,axmovbx,msg0callput_string;显⽰第⼀段信息pushword[es:code_2_segment]movax,beginpushaxretf;可以直接pushbegin,80386+;转移到代码段2执⾏movax,[es:data_2_segment];段寄存器DS切换到数据段2movds,axmovbx,msg1callput_stringjmp$;显⽰第⼆段信息;===============================================================================SECTIONcode_2align=16vstart=0;定义代码段2(16字节对齐)begin:pushword[es:code_1_segment]movax,continuepushaxretf;可以直接pushcontinue,80386+;转移到代码段1接着执⾏;===============================================================================SECTIONdata_1align=16vstart=0msg0db'ThisisNASM-thefamousNetwideAssembler.'db'BackatSourceForgeandinintensivedevelopment!'db'Getthecurrentversionsfromhttp://www.nasm.us/.'db0x0d,0x0a,0x0d,0x0adb'Examplecodeforcalculate1+2+...+1000:',0x0d,0x0a,0x0d,0x0adb'xordx,dx',0x0d,0x0adb'xorax,ax',0x0d,0x0adb'xorcx,cx',0x0d,0x0adb'@@:',0x0d,0x0adb'inccx',0x0d,0x0adb'addax,cx',0x0d,0x0adb'adcdx,0',0x0d,0x0adb'inccx',0x0d,0x0adb'cmpcx,1000',0x0d,0x0adb'jle@@',0x0d,0x0adb'......(Someothercodes)',0x0d,0x0a,0x0d,0x0adb0;===============================================================================SECTIONdata_2align=16vstart=0msg1db'TheabovecontentsiswrittenbyLeeChung.'db'2011-05-06'db0;===============================================================================SECTIONstackalign=16vstart=0resb256stack_end:;===============================================================================SECTIONtrailalign=16program_end:c09_1.asm;代码清单9-1;⽂件名:c09_1.asm;⽂件说明:⽤户程序;创建⽇期:2011-4-1622:03;===============================================================================SECTIONheadervstart=0;定义⽤户程序头部段program_lengthddprogram_end;程序总长度[0x00];⽤户程序⼊⼝点code_entrydwstart;偏移地址[0x04]ddsection.code.start;段地址[0x06]realloc_tbl_lendw(header_end-realloc_begin)/4;段重定位表项个数[0x0a]realloc_begin:;段重定位表code_segmentddsection.code.start;[0x0c]data_segmentddsection.data.start;[0x14]stack_segmentddsection.stack.start;[0x1c]header_end:;===============================================================================SECTIONcodealign=16vstart=0;定义代码段(16字节对齐)new_int_0x70:pushaxpushbxpushcxpushdxpushes.w0:moval,0x0a;阻断NMI。当然,通常是不必要的oral,0x80out0x70,alinal,0x71;读寄存器Atestal,0x80;测试第7位UIPjnz.w0;以上代码对于更新周期结束中断来说;是不必要的xoral,aloral,0x80out0x70,alinal,0x71;读RTC当前时间(秒)pushaxmoval,2oral,0x80out0x70,alinal,0x71;读RTC当前时间(分)pushaxmoval,4oral,0x80out0x70,alinal,0x71;读RTC当前时间(时)pushaxmoval,0x0c;寄存器C的索引。且开放NMIout0x70,alinal,0x71;读⼀下RTC的寄存器C,否则只发⽣⼀次中断;此处不考虑闹钟和周期性中断的情况movax,0xb800moves,axpopaxcallbcd_to_asciimovbx,12*160+36*2;从屏幕上的12⾏36列开始显⽰mov[es:bx],ahmov[es:bx],ahmov[es:bx+2],almoval,':';显⽰两位⼩时数字;显⽰分隔符':'mov[es:bx+4],alnotbyte[es:bx+5];反转显⽰属性popaxcallbcd_to_asciimov[es:bx+6],ahmov[es:bx+8],almoval,':';显⽰两位分钟数字mov[es:bx+10],al;显⽰分隔符':'notbyte[es:bx+11];反转显⽰属性popaxcallbcd_to_asciimov[es:bx+12],ahmov[es:bx+14],al;显⽰两位⼩时数字moval,0x20;中断结束命令EOIout0xa0,alout0x20,alpopes;向从⽚发送;向主⽚发送popdxpopcxpopbxpopaxiret;-------------------------------------------------------------------------------bcd_to_ascii:;BCD码转ASCII;输⼊:AL=bcd码;输出:AX=asciimovah,al;分拆成两个数字andal,0x0f;仅保留低4位addal,0x30;转换成ASCIIshrah,4;逻辑右移4位andah,0x0faddah,0x30ret;-------------------------------------------------------------------------------start:movax,[stack_segment]movss,axmovsp,ss_pointermovax,[data_segment]movds,axmovbx,init_msgcallput_stringmovbx,inst_msgcallput_string;显⽰初始信息;显⽰安装信息moval,0x70movbl,4mulbl;计算0x70号中断在IVT中的偏移;防⽌改动期间发⽣新的0x70号中断movbx,axclipushesmovax,0x0000moves,axmovword[es:bx],new_int_0x70;偏移地址。movword[es:bx+2],cspopes;段地址moval,0x0b;RTC寄存器Boral,0x80;阻断NMIout0x70,almoval,0x12;设置寄存器B,禁⽌周期性中断,开放更码,24⼩时制out0x71,al;新结束后中断,BCDmoval,0x0cout0x70,alinal,0x71;读RTC寄存器C,复位未决的中断状态inal,0xa1;读8259从⽚的IMR寄存器andal,0xfe;清除bit0(此位连接RTC)out0xa1,alsti;写回此寄存器;重新开放中断movbx,done_msg;显⽰安装完成信息callput_stringmovbx,tips_msgcallput_stringmovcx,0xb800movds,cx;显⽰提⽰信息movbyte[12*160+33*2],'@';屏幕第12⾏,35列.idle:hlt;使CPU进⼊低功耗状态,直到⽤中断唤醒notbyte[12*160+33*2+1];反转显⽰属性jmp.idle;-------------------------------------------------------------------------------put_string:;显⽰串(0结尾)。;输⼊:DS:BX=串地址movcl,[bx]orcl,cl;cl=0?jz.exit;是的,返回主程序callput_charincbx;下⼀个字符jmpput_string.exit:ret;-------------------------------------------------------------------------------put_char:;显⽰⼀个字符;输⼊:cl=字符asciipushaxpushbxpushcxpushdxpushdspushes;以下取当前光标位置;以下取当前光标位置movdx,0x3d4moval,0x0eoutdx,almovdx,0x3d5inal,dx;⾼8位movah,almovdx,0x3d4moval,0x0foutdx,almovdx,0x3d5inal,dx;低8位movbx,ax;BX=代表光标位置的16位数cmpcl,0x0d;回车符?jnz.put_0amovbl,80;不是。看看是不是换⾏等字符movax,bx;divblmulblmovbx,axjmp.set_cursor.put_0a:cmpcl,0x0a;换⾏符?jnz.put_other;不是,那就正常显⽰字符addbx,80jmp.roll_screen.put_other:;正常显⽰字符movax,0xb800moves,axshlbx,1mov[es:bx],cl;以下将光标位置推进⼀个字符shrbx,1addbx,1.roll_screen:cmpbx,2000;光标超出屏幕?滚屏jl.set_cursormovax,0xb800movds,axmoves,axcldmovsi,0xa0movdi,0x00movcx,1920repmovswmovbx,3840;清除屏幕最底⼀⾏movcx,80.cls:movword[es:bx],0x0720addbx,2loop.clsmovbx,1920.set_cursor:movdx,0x3d4moval,0x0eoutdx,almovdx,0x3d5movdx,0x3d5moval,bhoutdx,almovdx,0x3d4moval,0x0foutdx,almovdx,0x3d5moval,bloutdx,alpopespopdspopdxpopcxpopbxpopaxret;===============================================================================SECTIONdataalign=16vstart=0init_msginst_msgdone_msgtips_msgdb'Starting...',0x0d,0x0a,0db'Installinganewinterrupt70H...',0db'Done.',0x0d,0x0a,0db'Clockisnowworking.',0;===============================================================================SECTIONstackalign=16vstart=0resb256ss_pointer:;===============================================================================SECTIONprogram_trailprogram_end:————————————————版权声明:本⽂为CSDN博主「ARM的程序员敲着诗歌的梦」的原创⽂章,遵循CC4.0BY-SA版权协议,转载请附上原⽂出处链接及本声明。原⽂链接:/longintchar/article/details/50446330c11_mbr.asm;代码清单11-1;⽂件名:c11_mbr.asm;⽂件说明:硬盘主引导扇区代码;创建⽇期:2011-5-1619:54;设置堆栈段和栈指针movax,csmovss,axmovsp,0x7c00;计算GDT所在的逻辑段地址movax,[cs:gdt_base+0x7c00];低16位movdx,[cs:gdt_base+0x7c00+0x02];⾼16位movbx,16divbxmovds,axmovbx,dx;令DS指向该段以进⾏操作;段内起始偏移地址;创建0#描述符,它是空描述符,这是处理器的要求movdword[bx+0x00],0x00movdword[bx+0x04],0x00movdword[bx+0x04],0x00;创建#1描述符,保护模式下的代码段描述符movdword[bx+0x08],0x7c0001ffmovdword[bx+0x0c],0x00409800;创建#2描述符,保护模式下的数据段描述符(⽂本模式下的显⽰缓冲区)movdword[bx+0x10],0x8000ffffmovdword[bx+0x14],0x0040920b;创建#3描述符,保护模式下的堆栈段描述符movdword[bx+0x18],0x00007a00movdword[bx+0x1c],0x00409600;初始化描述符表寄存器GDTRmovword[cs:gdt_size+0x7c00],31;描述符表的界限(总字节数减⼀)inal,0x92;南桥芯⽚内的端⼝lgdt[cs:gdt_size+0x7c00]oral,0000_0010Bout0x92,alcli;打开A20;保护模式下中断机制尚未建⽴,应;禁⽌中断moveax,cr0oreax,1movcr0,eax;设置PE位;以下进⼊保护模式......jmpdword0x0008:flush;清流⽔线并串⾏化处理器[bits32];16位的描述符选择⼦:32位偏移flush:movcx,00000000000_10_000Bmovds,cx;加载数据段选择⼦(0x10);以下在屏幕上显⽰"ProtectmodeOK."movbyte[0x00],'P'movbyte[0x02],'r'movbyte[0x04],'o'movbyte[0x06],'t'movbyte[0x08],'e'movbyte[0x0a],'c'movbyte[0x0c],'t'movbyte[0x0e],''movbyte[0x10],'m'movbyte[0x12],'o'movbyte[0x14],'d'movbyte[0x16],'e'movbyte[0x18],''movbyte[0x1a],'O'movbyte[0x1c],'K';以下⽤简单的⽰例来帮助阐述32位保护模式下的堆栈操作movcx,00000000000_11_000Bmovss,cx;加载堆栈段选择⼦movesp,0x7c00movebp,esp;保存堆栈指针pushbyte'.';压⼊⽴即数(字节)subebp,4cmpebp,espjnzghalt;判断压⼊⽴即数时,ESP是否减4popeaxmov[0x1e],alghalt:;显⽰句点hlt;已经禁⽌中断,将不会被唤醒;-------------------------------------------------------------------------------gdt_sizedw0gdt_basedd0x00007e00;GDT的物理地址times510-($-$$)db0db0x55,0xaac12_mbr.asm;代码清单12-1;⽂件名:ex12-1.asm;⽂件说明:硬盘主引导扇区代码;创建⽇期:16:232018/5/30;---------------------------------------------------------------;定义常量;---------------------------------------------------------------MEMORY_STARTequ0x100000;要检测的内存起始地址MEMORY_ENDequ0x500000;要检测的内存结束地址MEMORY_SIZEequ(MEMORY_END-MEMORY_START)/4;以双字位单元;---------------------------------------------------------------;设置堆栈段和栈指针moveax,csmovss,eaxmovsp,0x7c00;计算GDT所在的逻辑段地址moveax,[cs:pdgt+0x7c00+0x02];GDT的32位线性基地址xoredx,edxmovebx,16divebx;分解成16位逻辑地址movds,eax;令DS指向该段以进⾏操作:EAX低16位有效DS=0x7e00movebx,edx;段内起始偏移地址:EDXEBX低16位有效ebx=0x0000;创建0#描述符,它是空描述符,这是处理器的要求movdword[ebx+0x00],0x00000000movdword[ebx+0x04],0x00000000;创建1#描述符,这是⼀个数据段,对应0~4GB的线性地址空间movdword[ebx+0x08],0x0000ffff;段基地址0x00000000movdword[ebx+0x0c],0x00cf9200;创建2#描述符,这是⼀个只执⾏的代码段movdword[ebx+0x10],0x7c0001ff;段基地址0x00007C00movdword[ebx+0x14],0x00409800;创建3#描述符,这是上⾯代码段的别名movdword[ebx+0x18],0x7c0001ff;段基地址0x00007C00movdword[ebx+0x1c],0x00409200;创建4#描述符,这是栈段movdword[ebx+0x20],0x7c00fffe;段基地址0x00007C00movdword[ebx+0x24],0x00cf9600;初始化描述符寄存器GDTRmovword[cs:pdgt+0x7c00],39;5*8-1=39lgdt[cs:pdgt+0x7c00]inal,0x92;南桥芯⽚的端⼝oral,0000_0010Bout0x92,alcli;打开A20moveax,cr0oreax,1movcr0,eax;设置PE位;以下进⼊保护模式......jmpdword0x0010:flush[bits32]flush:moveax,0x0018;索引号3#movds,eaxmoveax,0x0008;索引号1#moves,eaxmovfs,eaxmovgs,eaxmoveax,0x0020;索引号4#movss,eaxxoresp,esp;ESP=0movdword[es:0x0b8000],0x072e0750;'P.'movdword[es:0x0b80
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026北京化工大学巴黎居里工程师学院物理实验助理招聘1人备考题库及完整答案详解(必刷)
- 2026甘肃省人力资源市场招聘就业见习人员6人备考题库【夺分金卷】附答案详解
- 2026年春季河北邯郸市鸡泽县博硕人才选聘10人备考题库附答案详解(黄金题型)
- 中国航空油料招聘笔试题及答案
- 2026福建莆田城厢法院招聘3人备考题库(a卷)附答案详解
- 2026上半年四川成都经济技术开发区(龙泉驿区)考核招聘事业单位人员10人备考题库及参考答案详解【典型题】
- 2026上海市信息安全测评认证中心招聘2人备考题库及答案详解【有一套】
- 2026宁夏银川丽人妇产医院招聘28人备考题库及参考答案详解(典型题)
- 2026内蒙古呼和浩特市玉泉区桃花乡卫生院招聘1人备考题库及答案详解(名师系列)
- 2026太平洋证券有限责任公司招聘5人备考题库及参考答案详解1套
- 3.12.2024新苏教版小学科学三年级下册第三单元第12课《石头上的植物》同步课件
- 金华义乌市供销联社下属企业2026年招聘6人笔试模拟试题及答案解析
- 2026届湖北省武汉普通高中高三3月调考数学+答案
- 学校推进生源转型期的小班化教学工作方案:让生源减少的“挑战”转化为办学质量提升的“红利”
- (一模)包头市2026年高三第一次模拟考试地理试卷(含答案)
- 2026年湖南省长沙市高职单招职业技能考试题库带答案详解
- 2026年无锡科技职业学院单招综合素质考试题库有答案详解
- DB54∕T 0601-2026 农作物品种生产示范技术规程 青稞
- XX区实验学校初中部2026年春季学期中期学生社团管理实施方案
- 2026年六安职业技术学院单招职业适应性考试题库及答案详解(夺冠)
- 1.2 幸福生活是奋斗出来的 第1课时 课件+视频-2025-2026学年道德与法治三年级下册统编版
评论
0/150
提交评论