??xml version="1.0" encoding="utf-8" standalone="yes"?>国产三级视频在线播放线观看,亚洲成人套图,中文字幕亚洲精品http://www.aygfsteel.com/ThinkingTalking/category/26284.htmlDo what I can do!zh-cnSun, 30 Sep 2007 17:05:08 GMTSun, 30 Sep 2007 17:05:08 GMT60防范U盘病毒Autorun.inf的绝?/title><link>http://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149750.html</link><dc:creator>ThinkingTalking</dc:creator><author>ThinkingTalking</author><pubDate>Sun, 30 Sep 2007 01:04:00 GMT</pubDate><guid>http://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149750.html</guid><wfw:comment>http://www.aygfsteel.com/ThinkingTalking/comments/149750.html</wfw:comment><comments>http://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149750.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/ThinkingTalking/comments/commentRss/149750.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/ThinkingTalking/services/trackbacks/149750.html</trackback:ping><description><![CDATA[<div id="wmqeeuq" class="NewsContent" id="NewsContentLabel"> <p>目前QU盘病毒的情况非常严重。几乎所有带病毒的U?根目录里都有一个autorun.infQ右键菜单多?#8220;自动播放”?#8220;Open”?#8220;Browser”{项目。由于我们习(fn)惯用双击来打开盘Q但现在我们双击Q通常不是打开U盘,而是让autorun.inf里所讄E序自动播放。只需采用鼠标右键单击打开׃?x)激zȝ毒。但若你的机子有很多人,又不能保证他们不?x)双(yn)L开U盘,那就可以采用下面的方法?/p> <p>  招一、组{略关闭AutoRun功能(适合不熟(zhn)?a class="UBBWordLink" target="_blank">?sh)?/a>?</p> <p>  如果你想一ơ全部禁?a class="UBBWordLink" target="_blank">Windows</a> XP的自动播攑֊能,那么h下述步骤操作Q?/p> <p>  1、单?#8220;开?#8594;q行”Q在“打开”框中Q键?#8220;gpedit.msc”Q单?#8220;定”按钮Q打开“l策?#8221;H口;</p> <p>  2、在左窗格的“本地计算机策?#8221;下,展开“计算机配|?#8594;理模板→<a class="UBBWordLink" target="_blank">pȝ</a>”Q然后在右窗格的“讄”标题下,双击“关闭自动播放”;</p> <p>  3、单?#8220;讄”选项卡,选中“已启?#8221;复选钮Q然后在“关闭自动播放”框中单击“所有驱动器”Q单?#8220;定”按钮Q最后关?#8220;l策?#8221;H口?/p> <p>  招二、注册表关闭AutoRun功能</p> <p>  ?#8220;开?#8221;菜单?#8220;q行”中输入RegeditQ打开注册?a class="UBBWordLink" target="_blank">~辑</a>器,展开?/p> <p>  HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Exploer 主键下,在右侧窗g扑ֈ“NoDriveTypeAutoRun”Q就是这个键军_了是否执行CDROM?a class="UBBWordLink" target="_blank">盘</a>的AutoRun功能?/p> <p>  双击 “NoDriveTypeAutoRun”Q在默认状态下(即你没有止qAutoRun功能)Q在弹出H口中可以看?“NoDriveTypeAutoRun”默认键gؓ(f)95,00,00,00Q附件上传了抓图。其中第一个?#8220;95”是十六进制|它是所有被止自动q?行设备的和。将“95”转ؓ(f)二进制就?0010101Q其中每位代表一个设备,<a class="UBBWordLink" target="_blank">Windows</a>中不同设备会(x)用如下数DC:(x)</p> <p>  讑֤名称 W几??讑֤用如下数DC?讑֤名称含义</p> <p>  DKIVE_UNKNOWN   0101h 不能识别的设备类?br /> <br /> </p> <div id="wmqeeuq" class="NewsContent" id="NewsContentLabel">DRIVE_NO_ROOT_DIR 1002h 没有根目录的驱动?Drive without root directory) <p> </p> <p>  DRIVE_REMOVABLE  2104h 可移动驱动器(Removable drive)</p> <p>  DRIVE_FIXED  3008h 固定的驱动器(Fixed drive)</p> <p>  DRIVE_REMOTE 4110h <a class="UBBWordLink" target="_blank">|络</a>驱动?Network drive)</p> <p>  DRIVE_CDROM 5020h 光驱(CD-ROM)</p> <p>  DRIVE_RAMDISK 6040h RAM盘(RAM Disk)</p> <p>  保留 7180h 未指定的驱动器类?/p> <p>  在上面所列的表中gؓ(f)“0”表示讑֤q行Qgؓ(f)“1”表示该设备不q行(默认情况下,<a class="UBBWordLink" target="_blank">Windows</a>止80h?0h?h?1hq些讑֤自动q行Q这些数值篏加正好是十六q制?5hQ所以NoDriveTypeAutoRun”默认键gؓ(f)95,00,00,00)?/p> <p> 招三、修Ҏ(gu)限法</p> <p>  1. 点开?>q行 输入 regedit.exe 回R 2. 打开注册?a class="UBBWordLink" target="_blank">~辑</a>器后展开,也是q入</p> <p>  [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2] 3. 右键点MountPoints2 选择权限 4. 依次点击“<a class="UBBWordLink" target="_blank">安全</a>中的用户和组”Q在下面的权限中都改成拒l?5. h一遍,此后即U盘有病毒也不?x)激z,双击U盘会(x)正常q入U盘?/p> <p>  招四、隐藏驱动器?适合U盘用频J者,如打印工作室)</p> <p>  如果上面的方法都不够dQ还有一招就是把驱动器隐藏了Q而用一个批处理文g来打开U盘?/p> <p>  1、打开注册?a class="UBBWordLink" target="_blank">~辑</a>器,q是q入</p> <p>  HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\ExplorerQ新Zq制?#8220;NoDrives”Q缺省值是00000000Q表CZ隐藏M驱动器。键值由4个字节组成,每个字节的每一?bit)对应从A到Z的一个盘Q当相应位ؓ(f)1Ӟ“我的<a class="UBBWordLink" target="_blank">?sh)?/a>”中的相应驱动器就被隐藏了。第一个字节代表从A到H的八个盘Q即01为A?2为B?4为C……依此cLQ第二个字节代表I到P;W三个字节代表Q到X;W四个字节代表Y和Z。U盘的盘符是接着现有盘符往下推。若你现在已l用了C、D、E、FQ那么U盘采用GQ着盘符Q再插入一个U盘就用HQ。此时只需GQ和HQ隐藏,则插入U盘也不会(x)?#8220;我的<a class="UBBWordLink" target="_blank">?sh)?/a>”里显C。当?dng)用注册?a class="UBBWordLink" target="_blank">~辑</a>器修Ҏ(gu)册表操作h较ؓ(f)复杂Q?现在有很多专门修Ҏ(gu)册表的YӞ?a class="UBBWordLink" target="_blank">WINDOWS</a>优化大师中展开</p> </div> <div id="wmqeeuq" class="NewsContent" id="NewsContentLabel">“<a class="UBBWordLink" target="_blank">pȝ</a>性能优化/pȝ<a class="UBBWordLink" target="_blank">安全</a>优化/更多讄/选择要隐藏的驱动?#8221;Q将要隐藏的盘符前的"?里打"√",定卛_? <p> </p> <p>  2、在桌面新徏一个文本文Ӟ输入“start (你的盘符):”Q如Q?#8220;start f:\”,另存?#8220;q入U?bat”Q之后就通过双击该批处理文g来打开U盘,不仅可防病毒Q用也很方ѝ?/p> <p>  招五、禁止创建autorun.inf(保护自己的U?</p> <p>  在根目录下徏立一个文件夹Q名字就叫autorun.inf。由?a class="UBBWordLink" target="_blank">Windows</a>规定在同一目录中,同名的文件和文g夹不能共存,q样病毒无法创建autorun.ini文gQ即使?zhn)双击盘符也不会(x)运行病毒?/p> <p> </p> </div> </div> <img src ="http://www.aygfsteel.com/ThinkingTalking/aggbug/149750.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/ThinkingTalking/" target="_blank">ThinkingTalking</a> 2007-09-30 09:04 <a href="http://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149750.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用汇~编写DOS下的内存ȝE序(1)http://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149743.htmlThinkingTalkingThinkingTalkingSun, 30 Sep 2007 00:22:00 GMThttp://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149743.htmlhttp://www.aygfsteel.com/ThinkingTalking/comments/149743.htmlhttp://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149743.html#Feedback0http://www.aygfsteel.com/ThinkingTalking/comments/commentRss/149743.htmlhttp://www.aygfsteel.com/ThinkingTalking/services/trackbacks/149743.htmll言
0.1 内存ȝ与中?
内存ȝE序英文叫Terminate and Stay Resident Program,~写为TSR.q些E序加蝲q内?执行完后,驻留在内存?当满x件时,调到前台来执行?
内存ȝE序的常用Ş式有:
>诸如Borland 的SideKick弹出式实用程?
>日历pȝ
>|络服务?
>通讯E序
>本地的DOS扩展(如CCDOS,UCDOS{中文系l都属于q个范畴)
>一些可恶的人利用TSR技?/a>制作很多可恶的病毒程?几乎所有的病毒E序都是TSRE序.
p多Q务系l调度一个进E有一个调度程序一?在PC中从前台E序q入C个TSR,也要有一个调度?只是PC操作pȝ的调度不UCؓ(f)调度E序,而只UCؓ(f)触发机制.触发机制调度TSR执行在PCZ党称为激zM个TSR.触发机制主要有以下几U?
>g中断:党用的是键盘中断INT 9H,旉中断INT 8H,通讯中断INT 14H,盘中断INT 13H{等.
>软g中断:党用的是键盘中断INT 16H,旉中断INT 1CH,DOS中断INT 21H,{等.
>以上各种的结?
从以上的触发机制可以看出,TSR和PC机的中断pȝ有着密切的关p?每种ȀzL式实际上都是与中断有关的.常用Ҏ(gu)的击键序列的识别码是通过截获INT 9H和INT 16H来实?实际上不TSRE序的哪一个环?都与中断有着密切的关p?因此在具体进行TSR和程序设计之?先介lPC中断pȝ.在此只作单说?
在PC机内存的最低端(0000H开??K字节?存放着256个指针即常说的中为向量或中断矢量(Interrupt vertor)Q每个中断向量都指向一个子E序Q该E序UCؓ(f)中断处理E序QInterrup handler)Q一个中断向量由四个字节l成Q有一个字是中断处理程序的偏移量|后一个字是中断处理程序的D|256中断向量一L(fng)Z断向量表.
手式计算中断向量的首址,可通过以下的公式来求得:
X号中断向量的首址=0000H:X*4
当生一个中断时,处理器都按顺序执行以下步?
>在堆栈上压入处理器的标志(相当于指令PUSHF).
>在堆栈上压入当前CS和IP?相当于指令PUSH CS和PUSH IP).
>关闭中断(CLI)
>从中断向量加载的CS和IP,执行中断处理E序.
当执行完中断处理E序?一般用IRETq回,它的作用?
>从堆栈上取出保存的IP和CS(相当于指令POP CS和PUSH CS).
>同时恢复中断前的处理器标?相当于指令POPF).
中断有多U分c?p发的原因和实现的性质来分,可分为硬件中断和软g中断,从操作系l分层实现来?可以分成BIOS中断,BOS中断和用户中?
一斚w,BIOS和DOS通过中断pȝ向用h供一个操作系l功能界?也就是说用户(一般来说是前台E序)的功能主要是通过调用DOS和BIOS的中?a class="channel_keylink" >服务
来实现的,具体来说是通过INT指o(h)来实现的.另一斚w,BIOS和DOS׃断系l所构成,BIOS对硬件成为高层的功能,q过中断的Ş式向用户提供.
如果在当前程序执行的同时,能将一块代码放在内?把中断向量指向代码中的子E序,那么在当前程序执行中产生中断?有可能执行不属于当前程序和操作pȝ的代?产生的中断可能是当前E序产生的Y件中?也可能是q件生的g中断.q就是单d的PC操作pȝ可能执行多于一个进E的单说?
在PC中断pȝ中有几个中断h周期?即INT 8H,INT 1CH和INT 28H.它们或者周期性被执行用于旉计时,或者周期性生用于等?它们是在实现TSR时进行轮询触发的基础.键盘中断(INT 9H和INT 16H)当用户击键时发生,利用它们是进行热键处理的基础.串行口通讯也是触发的一个重要机?此外众多的Y件中断也是触发的媒介.

0.2 DOS的可重入性分?
一个多d操作pȝ之所以能使多个进行ƈ?是因为操作系l的大部分代码是可以了重?对于临界资源有相应的PV操作,使得当调度一个新的进E时,能完整地保存前一个里E的现场,当再一ơ调度被挂v的进E时能象没有被中断一L(fng)l执?
对于PC机来?代码的重入性比较弱,对(f)界资源没有PC操作.当我们用中断E序启动用户的TSR?如果只保存标志和寄存?以及(qing)当前q程一些信?那么只保存了当前E序的一部分现场,DOS的(f)界资源不?a class="channel_keylink" >自动保存.在进行TSR设计?一定要了解PC操作pȝ的重入性和临界资源.
重入性L体现在代码上,所谓可重入代码的指q样的代?卌代码被执行时q没有从中退?׃某种原因又一ơ或者多ơ进入相同的代码,该代码每ơ的执行l果都是正确?p该代码是可重入的.相反,如果l果不正?那么就该代码是不可重入?下面是一个可重入的子E序的例?
Add proc near
cmp DS:word ptr [si],0
je DonotAddTheValue
add ax,DS:word ptr [si]
DonotAddTheValue:
ret
Add endp
上面的例子不在其中M一处再一ơ执行该子程?执行l果不变.Z说明,只D多种可能性中的一U?
mov ds,0100h ;ds=0100h
mov si,0010h ;si=0010h
mov ax,0001h ;ax,=0001h
call Add
cmp 0100h:word ptr [0010h],0 ;Call Add subroutine
push ds ;Interrupted
push si
push ax
mov ds,0200h ;ds=0200h
mov si,0200h ;si=0020h
mov ax,0003h ;ax=0003h
call Add
cmp 0200h:word ptr [0020h],0 ;0200:0020h=0004h
jne
add ax,0200h:word ptr [0020h] ;ax=0007h
ret ;Return
pop ax ;ax=0001h
pop si ;si=0010h
pop ds ;ds=0100h
iret ;Return to Add subroutine
jne
add ax,0100h:word ptr [0100h] ;ax= 0001h
;0100h:0010h= 0002h
;----------------------------------------
;ax = 0003h
ret
mov bx,ax
而下面的子程序是不可重入?
Add proc near
mov Temp,ax
mov ax,DS:word ptr [si]
cmp ax,0
je DonotTheValue
add ax,Temp
DonotTheValue:
ret
Temp:
dw 0
Add endp
可以利用(g)查可重入子程序的Ҏ(gu)(g)查这个子E序的不可重入?试一下在" mov ax,DS:word ptr [si]"指o(h)后再ơ执行该子程?那么׃(x)出第一ơ调用返回的l果不对.
mov ds,0100h ;ds=0100h
mov si,0010h ;si=0010h
mov ax,0001h ;ax,=0001h
call Add
mov Temp,ax ;Call Add subroutine
;Temp=0001h
mov ax,0100h:word ptr [0010h] ;0100h:0010h=0002h
;ax=2
push ds ;Interrupted
push si
push ax
mov ds,0200h ;ds=0200h
mov si,0020h ;si=0020h
mov ax,0003h ;ax=0003h
call Add
mov Temp,ax ;Temp=0003h
mov ax,0200h:word ptr [0020h] ;0200h:0020h=0004h
cmp ax,0 ;ax=0004h
jne ;Not equal ,add
add ax,Temp ;ax=0007h
ret ;Return to the interrupted point
pop ax ;ax=0002h
pop si ;si=0010h
pop ds ;ds=0100h
iret ;Return to Add subroutine
cmp ax,0 ;ax=2
jne ;No equal,add
add ax,Temp ;ax =0002h
;0100h:0010h =0003h
;----------------------------------------
;ax =0005h
ret
mov bx,ax
上面执行的结果是AX=5,实上正确的结果应该是AX=3,q是׃当Add子程序从中断子程序再一ơ被调用?修改了Temp的?当从中断q回时不能正恢复其?
解决的方法是把Temp攑֜堆栈?当每ơAdd子程序被调用时Temp的地址都不一?因此原调用的Tempg?x)被W二ơ在中断中调用的Add所破坏.
Add proc near
push bp ;Store BP
sub sp,2 ;distribute a byte space in the stack
mov bp,sp ;SS:BP point to the stack head
temp equ SS:word ptr [BP+0] ;Explain the pointer to SS:BP
mov Temp,ax
mov ax,DS:word ptr [si]
cmp ax,0
je DonotAddTheValue
add ax,Temp
DonotAddTheValue:
add sp,2 ;Release the dsitributed space in the stack
pop bp ;Restore BP
ret
Add endp
对于DOS来说,DOS的内?a class="channel_keylink" >数据pTemp变量,它被分配?a class="channel_keylink" >数据?而不在堆栈上,因此DOS从M上是不可重入?从最后的一个例子看?重入性跟堆栈有很大的关系.可重入代码允许在M时候被中断,其所有的变量都存攑֜该代码的U有堆栈?DOS是一个单d的操作系l?在执行INT 21H的代码时是不允许中断DOS,q再ơ调用INT 21H?每个时该最多有一个进E在调用DOS的代?
对DOS的重入?以及(qing)相应所作的处理ȝ如下:
>当通过INT 21H调用DOS?DOS?x)三个内部栈之一:I/O?盘栈和辅助?功能00H到处0CH使用I/O?除了不致命错误处理程 序以外用磁盘栈,致命错误处理E序使用辅助?在这U栈切换模式?如果前台处在INT 22H?而TSR调用了用相同栈的DOS功能, ׃(x)使前台程序保存栈中的数据被TSR?a class="channel_keylink" >数据覆盖?但如果调用不同栈的DOS功能,那将是安全的.INT 21H中的几个功能调即33H,50H, 51H,62H,?4H׃非常?使用用户?因此在Q何情况下都是可重入的.避免q种不可重入的简单方法是当前台程序正处在INT 21H 中时,不要调用INT 21H.或者如果前台程序正在处理INT 21H?只允许调用不同栈的INT 21H功能.
>DOS数据Z有一个InDOS标志,也探源ؓ(f)DOS安全标志,表示当前讉KDOS功能是来否安?׃DOS不可重入,它指C当前是 否处于DOS?ȀzTSR和代码可(g)查该标志(34H),如果DOS?则不能激zM用INT 21H 调用的TSR.
>当前台程序执行能讄错误状态的DOS功能?DOS?x)把扩展错误信息存放h,正常情况?前台E序可以d扩展错误信息; 如果在前台程序读取信息之前激zTSR,且TSR也执行能报告错误信息的DOS功能,则后来的错误信息?x)覆盖原来的错误信?前台E序??x)得不到正确的错误信?因此必须在激zTSR之前保存(59H)q些错误信息,q在退Z前把它们恢复(5D0AH)成原来的?
>大多g中断如INT 13H,INT 0BH和INT 0CH{都是不可重往q?如果讄一引v寄存?而在此时被TSR打断,执行cM的设|?,׃(x)出现非常情况,端口是不?a class="channel_keylink" >自动保持值的.在进入这些中断时讄一个进入的标志,如果TSR(g)查到标志已置,则不调用相应的中?
>最好也不要重入INT 10H,INT 25H,和INT 26H中断.在进入这些中断时讄一个进入的标志,如果TSR(g)查到标志已置,则不调用 相应的中?
>最好能接管INT 1BH,INT 23H和INT 24H中断.
>保存DOS?a class="channel_keylink" >数据交换?SDA)可以安全C用的DOS的功?SDA保存了DOS几乎所有内?a class="channel_keylink" >数据,如果保存(5D06H)和恢?5D0BH)SDA ,DOS变成在M时候都可以重入的了.当DOS处在关键Z?调用INT 2AH.一旦处在关键区?׃能改变SDA.在关键区的结束处?调用INT21H?1H?2H功能.
0.3 内存ȝE序设计一般过E?
ȝE序分成两个部分,x驻部分和ȝ部分.ȝE序要完成安装检?Ȁzd删除{过E?
基本上可抽象成以下几个过E?
>取中断向?
>保存旧的中断向量
>讄或恢复中断向?
>中断处理E序的链?
>(g)是来呀已驻?
>执行l止q?
>TSR的删?
删除TSR比较复杂,必须按下列步骤进?
>(g)查中断向量是否已l被替换.如果没有替换,恢复所有的中断向量;如果某个中断向量被替?则蟩q下面各?不能删除?TSR.
>TSR的PSP中偏U量16H存放着父进E的PSP.把这个值改为当前进E的地址.
>把当前PSP设ؓ(f)TSR的PSP
>执行INT 21H?CH功能,释放TSR占用的内?关闭所有文?q用PSP中存攄父进E地址和终止地址.
>q里控制q回到初始进E中,当前PSP也指向初始进E?所有寄存器值包括SS和SP都不定.
在执行完上述步骤?要恢复寄存器.
如果要无条g地删除TSR,必须监控每个TSR对中断向量表,内存控制块和讑֤驱动E序铄修改.
0.5 ~写语表
ASCIZ: 以零l束的ASCII字符?
BPD: "BIOS Parameter Block (BIOS 参数?"的羃?含有寚w动器的低U参数的说明.
CDS: "Current Directory Structure(当前目录l构)"的羃?含有某个逻辑驱动器的当前目录,cd和其它信?
DPB: "DOS Drive Parameter Block(DOS驱动器参数块)"的羃?含有某个逻辑驱动器的介质说明?qing)一些内部信?
DPL: "DOS Parameter List (DOS参数?"的羃??a class="channel_keylink" >数据l构用来传递参数给SHARE?a class="channel_keylink" >|络功能调用.
DTA: "Disk Transfer Address(盘传输地址)"的羃?指示对磁盘进?a class="channel_keylink" >数据d的功能调用不必显式地l出~冲区地址.
FAT: "File Allocation Table(文g分配?"的羃?盘的文件分配表记录了所使用的簇信息.
FCB: "File Control Block(文g控制?"的羃?在DOS?.X版本?用FCB来记录文件打开的状?.
IFS: "Installable File System(可安装的文gpȝ)"的羃?它允怸个非DOS格式的介质被DOS所使用. 大多数情况下IFS ?a class="channel_keylink" >|络驱动器非常相?管IFS最典型的情冉|一个本地驱动器而不是一个远E驱动器.
JFT: "Job File Table(工作文g?或Open File Table(打开文g?"的羃?E序PSP中的JFT可用来将文g句柄转换成SFT?
NCB: "Network control Block( PSP: "Porgram Segment Prefix(E序D前~)"的羃?当程序被装入?PSPZ个预留的256字节?a class="channel_keylink" >数据区它包含了程序调用时 的命令行内容和一些DOS的内部信?
SDA: "DOS Swappable Data Area (DOSҎ(gu) SFT: "System File Table(pȝ文g?"的羃?SFT是一个DOS内部数据l构,在DOS 2+版本?/p> 句柄功能调用中用于管理某个已?开文g的状?q就和在DOS1.X?FCB理已打开文g状态一?

ThinkingTalking 2007-09-30 08:22 发表评论
]]>
用汇~编写DOS下的内存ȝE序(2)http://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149742.htmlThinkingTalkingThinkingTalkingSun, 30 Sep 2007 00:21:00 GMThttp://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149742.htmlhttp://www.aygfsteel.com/ThinkingTalking/comments/149742.htmlhttp://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149742.html#Feedback0http://www.aygfsteel.com/ThinkingTalking/comments/commentRss/149742.htmlhttp://www.aygfsteel.com/ThinkingTalking/services/trackbacks/149742.html 2.1 8086/8088
IBM PC中央处理单元(Central Processing Unit)是微处理器Inter 8088,8088?086是小的版?对于~写E序而言,两者几乎完全相?两者之间的差别是在?它们对外的沟?8086和外界沟通时是经?6位的输入输出通道,内存存取也是每次?6位ؓ(f)单位,8088?086极ؓ(f)怼,但是它和外界沟通时必ȝ?6位的通道.
2.1.1 寄存?
8086/8088的结构简?其中包含了一l一般用途的16位寄存器.AX,BX,CX,DX,BP,SI,DI.其中AX,BX,CX,DXq可以分?位的寄存 ?譬如:AX可分为AH,AL;BX可分为BH,BL;CX可分为CH,CL;DX可分为DH,DL.寄存器BP,SI,DI的用途也没有特别的限?但是却不能分成两个字?另外寄存器SP主要是用来当做堆栈指?除此之外,q有四个非常重要的段寄存?Segment Register):CS,DS,SS,ES.指o(h)指针(Instru -ction pointer)IP是用来控制目前CPU执行到哪一个指?
8086设计时考虑到要?位的CPU8080兼容.8位的计算机是使用两个字节(亦即16?来定址,因此其定址I间可以?4K字节.16位的CPU在地址讑֮上选择了完全不同的Ҏ(gu).CPU以段(Segment)为单?每一D范围内包括64K字节,而内存中则可以包含许多段.所?操作pȝ可以在一个段内执?而用者的E序则可以在另一个段内执?在一个段?E序包可以把计算为只?4K字节内存I间.因此原先8位计机上执行的E序可以很Ҏ(gu)地移植到16位计机?除此之外,内存D也可以彼此重叠,因而两个不同的E序可以共用某一块内?D值是以寄存器来设定的,而实际的地址值则是把D?16?往左移4?然后再加?6位的位移(Offset),因此构成20位的地址?所?086可以直接?0位的地址,也就是可能存取到一兆字节的内存.在这一兆字节的内存?IBM PC保留了最前面?20K字节l系l的ROM BIOS和显C内?因此使用者最多也p使用640K字节.
2.1.2 d方式
d方式(Addressing mode)是一台计机上许多复杂操作的关键所?8086提供了以下几U寻址Ҏ(gu):立即d,内存间接d, 寄存器间接寻址{?
立即d,直接使用数字.
内存间接d,数值存攑֜数据D中的某个位|?
mov bx,foo
foo dw 5
寄存器间接寻址.有两U寄存器可以使用在这U寻址方式?基址寄存?Base Register)和烦(ch)引寄存器(Index Register).基址寄存 器分别是BX和BP,索引寄存器则是SI和DI.在这U寻址方式?寄存器存放了数据D中的地址?
mov ax,0F000h
mov es,ax
mov si,0FFFEh
mov dl,byte ptr es:[si]
上面的程序用间接寻址方式,由寄存器SId位于F000:FFFE位置?a class="channel_keylink" >数据.寄存器间接存取时,最多只能用玛个基址寄存器各 一个烦(ch)引寄存器.
以上的寻址方式可以做不同的l合,因此l合后的l果很多.
2.1.3 标志
8086?个一位的标志(Flag),它们可以用指CCPU的各U状?以下?个标志的?
CF(Carry Flag):CF?时就表示术q算的结果超出正的长度.
PF(Parity Flag):PF?pCZ用偶校验,PF?pCZ用奇校验.
AF(Auxiliary Carry Flag):和CF相同,只是它用在?位的l果.AF通常都用在20位的地址计算?
ZF(Zero Flag):ZF?pC结果是0,否则ZF׃ؓ(f)0.
SF(Sign Flag):SF?pC结果的最高位?,否则SF׃ؓ(f)0.
TF(Trap Flag):TF?,CPU单步地执行,在这U模式下每完成一个指令就发生一个特D的中断.
IF(Interrupt Enable Flag):IF?,允许CPU接收外界的中?否则IF׃ؓ(f)0.
DF(Direction Flag):q个标志使用在@环指?譬如:MOVS,MOVSB,MOVSW,CMPS,CMPSB和CMPSW.如果DF?,循环q行时就使地 址值往前增?如果DF?,则地址往后减?
OF(Over Flag):OF?,表示一个考虑正负L(fng)q算出了正的字节的长?
2.1.4 循环
所有的循环指o(h)都是以CX作ؓ(f)计数?一个@环会(x)反复地执行直到CX{于某一特定gؓ(f)?以下的程序就是利用反复地相加,完成 两个数的怹.
mov ax,0
mov cx,4
next: add ax,6
loop next
在上面的E序?LOOP指o(h)执行时会(x)把CX?,q且(g)查CX的内?如果CX{于0,p{Ud下一条指?否则p到NEXT标示的地?执行.
也可以用下面的程序完成相同的功能:
mov ax,0
mov cx,4
next:
add ax,6
dec cx
cmp cx,0
jne next
2.1.5 内存?a class="channel_keylink" >数据l构
8088是以字节为存?a class="channel_keylink" >数据的基本单?计算机的存储l构?位的字节,但是CPU本n处理数据则是?6位ؓ(f)单位.在内存中,都遵 循一个原??高高低低的存储方?高字节对应高地址,低字节对应低地址.
下面是一个简单程?在AX中放入一个字节的内容q显C?
cseg segment
org 100h
assume cs:cseg,ds:cseg
start:
mov bx,cs
mov ds,bx
mov ah,'H'
mov al,'L'
mov test,ax
mov al,[si] ;First byte of test
call dchar
mov al,[si+1] ;Second byte of test
call dchar
ret
;Display the character contained in AL
dchar proc
push ax
push bx
mov bh,1
mov ah,0eh
int 10h
pop bx
pop ax
ret
dchar endp
test dw ?
cseg ends
end start

ThinkingTalking 2007-09-30 08:21 发表评论
]]>
用汇~编写DOS下的内存ȝE序(3)http://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149741.htmlThinkingTalkingThinkingTalkingSun, 30 Sep 2007 00:20:00 GMThttp://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149741.htmlhttp://www.aygfsteel.com/ThinkingTalking/comments/149741.htmlhttp://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149741.html#Feedback0http://www.aygfsteel.com/ThinkingTalking/comments/commentRss/149741.htmlhttp://www.aygfsteel.com/ThinkingTalking/services/trackbacks/149741.html 3.1 IBM PC提供的中?
IBM PC有两U基本Ş态的中断.如果是由外围讑֤所产生的中断就叫做g中断(Hardware interrupt),譬如:键盘,盘机和旉{外围设备都可以产生g中断.外围讑֤所产生的中断信号都q接C断控制器,中断控制器可以根据它们之间的重要性来安排优先序,以便使CPU有效地处理这些硬件信?另一U中断是软g中断(Software interrupt),软g中断也叫做陷?Trap),它是由执行中的Y件所产生.虽然软g包中断的处理方式和硬件中断完全相?但是通常软g中断是希望执行操作系l所提供?a class="channel_keylink" >服务.
?.1是IBM PC所提供的中?q些中断是根据中断号码和中断矢量(Interrupt vector)排列.
IBM PC的用h是编写应用程序的E序人员很少?x)直接接触到g中断,除非是用某些特D的g,或是需要较严格的要求时,最常被修改的硬件中断是敲键盘所产生的中?9H),其是文本编辑的E序.大体而言,只有g设计者基是系l程序h员才?x)注意到所有在g中断;~写内存ȝE序的设计h员则只用到部分g中断而已,其?键盘中断和计时器(Timer)的中?
反之,软g中断对于M~写?a class="channel_keylink" >~程序的?甚至对编写高U语aE序的h都相当的重要.软g中断是应用程序进入到IBM PC操作pȝ的接?l由q些接口应用E序才可以执行所要求的系l?a class="channel_keylink" >服务.
其中软g中断中最重要,同时也是最常被汇编语言E序设计师所用到是DOS INT 21H.q个中断是执行DOSpȝ调用的Y件中?它可以让应用E序执行MDOS的操?
接下来最有用的Y件中断是ROM-BIOS(基本输入输出pȝ)所提供的中?q些软g中断是IBM PC所提供的的低层?a class="channel_keylink" >服务,譬如:键盘输入,昄器输出和盘机的输入与输出等.
3.2 键盘输入的方?
以下׃IBM PC从键盘读取字Wؓ(f)例子,来说明中断的工作方式.IBM PC从键盘读取字W时,使用了两U不同Ş式中?亦即:g中断和Y件中?当用者从键盘敲下一个键?键盘的线路就?x)送出一个信?q个信号?x)造成g中断发生,从而触发低层次的键盘中断处理程序开始执?q个中断处理E序马上从键盘的gd使用者所敲入的字W?然后把它攑ֈ一个队列中,如果q个队列填满?键盘中断处理E序?x)IBM PC发出一声响.键盘中断处理E序做完q些事情之后,它就把控制权交还l原先被中断的程?如果有一个程序希望从键盘d一个字W时,它就发出适当的Y件中断信?q时候就q对应的中断处理程序去(g)查键盘队?q且传回队列中的W一个字W?
上面所介绍的键盘输入工作方?在中断驱动系l中很普遍地采用.q和做法可以把实际上需要输入的应用E序和实际上执行输入的处理部分分开?q种做法也可以用在其它不同Ş式的输入和输出外围设?
3.3 改变输入矢量
中断矢量储存在IBM PC最前面?00H个字节中.每一个矢量的长度是四个字节组?q四个字节内所存放的是中断处理E序执行的地址?其中前两个字节包含地址值的位移(Offset)部分,后面的两个字节则包含了段(Segment)部分.
中断矢量有两U修Ҏ(gu)?可以直接地设|中断矢量的地址?或是使用DOS所提供的系l调用设|中断矢量的地址?
3.3.1 直接讄中断矢量
因ؓ(f)中断矢量只是存放地址值的存储位置,因此我们可以直接地把地址存放到存储位|中.以下是一个小例子:
mov ax,0
mov es,ax
mov word ptr es:24,offset Keyboard
mov word ptr es:26,seg Keyboard
在许多情况下,上面的程序都可以正确地执?但是如果上面的程序正在执行时H然敲下一个键的话,可能会(x)问题;而最p的?冉|发生:W三个MOV已经执行完毕,而第四个MOV未执行?如果在此时敲下Q何键的话,键盘中断矢量都没有Q何意?而造成整个p?l死?因此我们可以在设|中断矢量时,让中断无?譬如:
mov ax,0
mov es,ax
cli
mov word ptr es:24,offset Keyboard
mov word ptr es:26,seg Keyboard
上面的做法在大部分的情况下都可以正确地执?但是CLIq个指o(h)无法停止NMI中断(不可屏蔽中断),因此如果发生NMI中断时就 没用办法.下面的这一U做法虽然比较复?但是对于所有的中断都有?q包括了NMI中断在内:
mov word ptr kbd-ptr[0],offset Keyboard
mov word ptr kbd-ptr[2],seg Keyboard
mov di,0 ;Use Di to Set ES to zero
mov es,di ;Set ES to destination segment
mov di,24 ;Set DI to destination offset
mov si,offset kbdptr ;set SI to source offset
mov cx,2 ;Set word count to 2
cld ;Set direction to forward
cli ;Disable interrupts
rep movsw ;Copy the new vector
sti ;Enable interrupts
kbdptr dd ?
上面的程序中,kbdptr是两个字?WORD)的指?Pointer),其中包含了键?中断处理E序的v始志?REPq个指o(h)根据寄?器CX所讄的次数来重复执行MOVSW,而整个指令就如同单一的指令一?NMI中断不能够发生在一个完整的指o(h)?因ؓ(f)地址值搬Uȝ?作都能包含在一个单一指o(h)?因此可以免除M中断的干?
3.3.2 使用DOS来设|中断矢?
因ؓ(f)要想安全地设|中断矢量需要一些技?因此DOS提供了一特D的服务,以帮助程序h员安全地讄中断矢量,如果只?DOS所提供的这?a class="channel_keylink" >服务来设定中断矢量的?那么׃必担心会(x)发生前面所叙述的差?DOS同时也提供了:d中断矢量?a class="channel_keylink" >服务.因ؓ(f)?取中断矢量的内容不会(x)修改pȝ的状?因此若直接写E序d,也很安全.但是如果你要自己直接d中断矢量的内Ҏ(gu),必计?Z断矢量的位置.而DOS已经提供了这?a class="channel_keylink" >服务.
使用DOS所提供的系l调?来读取中断矢量的内容?必须利用INT 21H中的函数35H(d中断矢量),q个函数热气矢量L(fng)?计算中断矢量的地址,然后q回其中的内?以下是一个例?
Old_Keyboard_IO dd ?
mov al,16h
mov ah,35h
int 21h
mov word ptr Old_Keyboard_IO,bx ;Offset of interrupt handler
mov word ptr Old_Keyboard_IO,es ;Segment of interrupt handler
用DOS来设|中断矢量例?
New_Keyboard_IO dd ?
mov word ptr New_Keyboard_IO,bx ;Offset of interrupt handler
mov word ptr New_Keyboard_IO,es ;Segment of interrupt handler
mov al,16h
mov ah,25h
int 21h
3.4 (g)查中断矢?
q里都是采用COM格式~程,可以建立一个BAT文g来处理写好的E序,以减击键次?设BAT文g名ؓ(f)MAKE.BAT:
MASM %1
LINK %1
EXE2BIN %1.EXE %1.COM
如果写好的程序名为MACRO.ASM,则可敲入:
C:\MAKE MACRO.ASM
卛_.
3.5 昄中断矢量
下面q个例子可以列出所有的重要的中断矢量内?在刚刚打开PC?q且没有执行MȝE序?可以发现所有的中断矢量D值都相同,q些地址值所存放的是ROM的程?当你修改中断矢量之后,可以利用这个程序观察到中断矢量的变?以下是IVEC.ASM的内?
cseg segment para public 'CODE'
org 100h
jmp start
assume cs:cseg,ds:cseg
start:
mov bx,cs ;Make data seg be the same as
mov ds,bx ;the code seg
call vectors
waitIn:
mov ah,0bh
int 21h
cmp al,0ffh
jne waitIn
mov ah,4ch
int 21h
;****************************************************************************
;Scan through display table,prinying two vectors per line
;If any record has an interrupt #=zero,this indicates
;end of the table.
;****************************************************************************
mov di,offset disptab ;Pointer to start of table
mov dh,0 ;Zero out top half of DX
vloop:
mov dl,[di] ;Get the interrupt number
cmp dl,0 ;If it's zero,we are done
je vdone ;so exit loop
add di,1 ;Advance pointer 1 byte
mov si,[di] ;Get pointer to description
call dvector ;Call the display routine
add di,2 ;Get the interrupt number
mov dl,[di] ;Advance to the next record
cmp dl,0 ;If it's zero,we are done
je vdone ;so exit loop
add di,1 ;Advance pointer 1 byte
mov si,[di] ;get pointer to description
call dvector ;Call the display routine
add di,2 ;Advance to the next record
jmp vloop
vdone: ;Print final CRLF
ret
vectors endp
;----------------------------------------------------------------------------
;Displays an interrupt vector.Display is in the form of
;<banner>,<interrupt#>,<seg>:<offset>
;where <interrupt #>,<seg>and<offset>
;are all dexadecimal numbers
;Call with
;DX -interrupt number
;DS:SI -pointer to banner string
;----------------------------------------------------------------------------
dvector proc near
call dstring ;Display the string in DS:SI
call dbyte ;Display the byte in DL
call dspace ;Display a space
call dspace
;
mov al,dl ;move the interrupt number to AL
mov ah,35h ;Function is Get interrupt vector
int 21h
mov dx,bx ;Move BX to DX so we can display
call ddword ;double-word in ES:DX
call dEndFra
call dcrlf ;Display a newline
ret
dvector endp
;----------------------------------------------------------------------------
;DS:SI points to ASCII string to be printed
;----------------------------------------------------------------------------
dstring proc near
push si
push ax
dis: mov al,[si] ;Fetch the next character
cmp al,0 ;If it's zero,we are done
je disdone
call dchar ;If not,point it
inc si ;Advance pointer to nest char
jmp dis
disdone:pop ax
pop si
ret
dstring endp
;----------------------------------------------------------------------------
;ES:DX contains double word to be displayed
;----------------------------------------------------------------------------
ddword proc near
push dx ;Save offset temporarily
mov dx,es ;Move segment to DX
call dsword ;Display segment
call dcolon ;Print a ";"
; call dcrlf
pop dx ;Restore offset to DX
call dsword ;Display offset
ret
ddword endp
;----------------------------------------------------------------------------
;DX containes single word to be displayed
;----------------------------------------------------------------------------
dsword proc near
push dx ;Save low byte temporarily
mov dl,dh ;Move high byte to low byte
call dbyte ;Display high byte
pop dx ;Restore low byte to DL
call dbyte ;Display low byte
ret
dsword endp
;----------------------------------------------------------------------------
;DL contains byte to be displayed
;----------------------------------------------------------------------------
dbyte proc near
push ax ;Save any registers used
push dx
push si
push dx ;Save low nybble temporarily
push cx ;Save CX
mov cl,4 ;Set shift count to 4
shr dx,cl ;Shift high nybble into low nybble
and dx,0fh ;Mask out all but low nybble
mov si,dx ;Use low nybble as index into
mov al,hextab[si] ;hexadecimal character table
call dchar ;Display character
pop cx ;Restore CX
pop dx ;Restore low nybble
and dx,0fh ;Mask out all but low nybble
mov si,dx ;Use low nybble as an index into
mov al,hextab[si] ;hexadecimal character table
call dchar ;Display character
pop si ;Restore registers
pop dx
pop ax
ret
dbyte endp
;----------------------------------------------------------------------------
;Display a ":"
;----------------------------------------------------------------------------
dcolon proc near
mov al,':'
call dchar
ret
dcolon endp
;----------------------------------------------------------------------------
;Display a " "
;--
--------------------------------------------------------------------------
dspace proc near
mov al,' '
call dchar
ret
dspace endp
;----------------------------------------------------------------------------
;Display a Carriage Return/Line Feed
;----------------------------------------------------------------------------
dcrlf proc near
mov al,0dh
call dchar
mov al,0ah
call dchar
ret
dcrlf endp
;----------------------------------------------------------------------------
;Display the character contained in AL
;----------------------------------------------------------------------------
dchar proc near
push ax
push bx
mov bh,1
mov ah,0eh
int 10h
pop bx
pop ax
ret
dchar endp
;----------------------------------------------------------------------------
;Data define
;----------------------------------------------------------------------------
hextab db '0123456789ABCDEF',0
disptab db 05h ;Print screen
dw v05
db 19h ;Bootstrap loader
dw v19
db 08h ;Timer tick
dw v08
db 1ah ;Real_time clock
dw v1a
db 09h ;Keyboard input
dw v09
db 1bh ;CTRL_Break handler
dw v1b
db 0bh ;Comm.port 1
dw v0b
db 1ch ;Timer control
dw v1c
db 0ch ;Comm.port 0
dw v0c
db 1dh ;Pointer to video parameter table
dw v1d
db 0dh ;Hard disk controller
dw v0d
db 1eh ;Pointer to disk parameter table
dw v1e
db 0eh ;Floppy disk controller
dw v0e
db 1fh ;Pointer graphics character table
dw v1f
db 0fh ;Printer controller
dw v0f
db 20h ;Program terminate
dw v20
db 10h ;Video driver
dw v10
db 21h ;DOS universal function
dw v21
db 11h ;Equipment check
dw v11
db 22h ;Pointer to termination handler
dw v22
db 12h ;Memorey size check
dw v12
db 23h ;Pointer to Ctrl_C handler
dw v23
db 13h ;Disk driver
dw v13
db 24h ;Pointer to critical error handler
dw v24
db 14h ;Communications driver
dw v14
db 25h ;Absolute disk read
dw v25
db 15h ;Cassette driver
dw v15
db 26h ;Absolute disk write
dw v26
db 16h ;Keyboard driver
dw v16
db 27h ;Terminate and stay resident
dw v27
db 17h ;Printer driver
dw v17
db 2fh ;Print spooler
dw v2f
db 18h ;Rom basic
dw v18
db 0
dw 0
v05 db 186,5 dup (20h),'Print screen:',26 dup (20h),0
v08 db 186,5 dup (20h),'Timer tick controller:',17 dup (20h),0
v09 db 186,5 dup (20h),'Keyboard input:',24 dup (20h),0
v0b db 186,5 dup (20h),'Communication port 1:',18 dup (20h),0
v0c db 186,5 dup (20h),'Communication port 0:',18 dup (20h),0
v0d db 186,5 dup (20h),'Hard disk controller:',18 dup (20h),0
v0e db 186,5 dup (20h),'Floppy disk controller:',16 dup (20h),0
v0f db 186,5 dup (20h),'Printer controller:',20 dup (20h),0
v10 db 186,5 dup (20h),'Video driver:',26 dup (20h),0
v11 db 186,5 dup (20h),'Equipment check:',23 dup (20h),0
v12 db 186,5 dup (20h),'Memory size check:',21 dup (20h),0
v13 db 186,5 dup (20h),'Disk driver:',27 dup (20h),0
v14 db 186,5 dup (20h),'Communication driver:',18 dup (20h),0
v15 db 186,5 dup (20h),'Cassette driver:',23 dup (20h),0
v16 db 186,5 dup (20h),'Keyboard driver:',23 dup (20h),0
v17 db 186,5 dup (20h),'Printer driver:',24 dup (20h),0
v18 db 186,5 dup (20h),'ROM BASIC:',29 dup (20h),0
v19 db 186,5 dup (20h),'Bootstrap loader:',22 dup (20h),0
v1a db 186,5 dup (20h),'Real_time clock:',23 dup (20h),0
v1b db 186,5 dup (20h),'Ctrl_break handler:',20 dup (20h),0
v1c db 186,5 dup (20h),'Timer control:',25 dup (20h),0
v1d db 186,5 dup (20h),'Video parameter table:',17 dup (20h),0
v1e db 186,5 dup (20h),'Disk parameter:',24 dup (20h),0
v1f db 186,5 dup (20h),'Graphic character table:',15 dup (20h),0
v20 db 186,5 dup (20h),'Programe terminate:',20 dup (20h),0
v21 db 186,5 dup (20h),'DOS universal function:',16 dup (20h),0
v22 db 186,5 dup (20h),'Terminate vector:',22 dup (20h),0
v23 db 186,5 dup (20h),'Ctrl_C vector:',25 dup (20h),0
v24 db 186,5 dup (20h),'Critical error vector:',17 dup (20h),0
v25 db 186,5 dup (20h),'Absolute disk read:',20 dup (20h),0
v26 db 186,5 dup (20h),'Absolute disk write:',19 dup (20h),0
v27 db 186,5 dup (20h),'Terminate and stay resident:',11 dup (20h),0
v2f db 186,5 dup (20h),'Print spooler:',25 dup (20h),0
cseg ends
end start

ThinkingTalking 2007-09-30 08:20 发表评论
]]>
用汇~编写DOS下的内存ȝE序(4)http://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149740.htmlThinkingTalkingThinkingTalkingSun, 30 Sep 2007 00:19:00 GMThttp://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149740.htmlhttp://www.aygfsteel.com/ThinkingTalking/comments/149740.htmlhttp://www.aygfsteel.com/ThinkingTalking/archive/2007/09/30/149740.html#Feedback0http://www.aygfsteel.com/ThinkingTalking/comments/commentRss/149740.htmlhttp://www.aygfsteel.com/ThinkingTalking/services/trackbacks/149740.html 4.1 一个基本的COME序
 DOS之下有两UŞ式的可执行文?q两U文件分别是COM文g和EXE文g.其中,COM文g可以q速地加蝲和执?但是其大不能超q?4K字节,只能有一个段,代码D?而且起始地址?00H指o(h)必须为程序的启动指o(h).EXE文g可以加蝲到许多个D中,因此E序的大没有限?但是E序加蝲的过E就比较?而且对于内存ȝE序来说q会(x)造成更大的麻?
 以下是一个可以正执行的COM文g,但其内容是空?只是一个COM文g的框?可以把你写的M应用部分加在q个文g?形成一个COM格式的内存驻留程?
  ;Section 1
  cseg segment
   assume cs:cseg,ds:cseg
    org 100h
  ;Section 2
  start: 
   ret
  ;Section  3
  cseg ends
   end start
 上面的程序可以分成三部分,W一部分定义了代码段?a class="channel_keylink" >数据D分别放在程序中的位|?以及(qing)执行代码的v始地址.W二部分是可执行的程?在这个例子只一个RET指o(h)而已.W三部分是程序包D늚l结,其中END叙述包含了程序开始执行地址.
 若是把上面的E序l过汇编q接,你会(x)发现所产生的COM文g只有一个字节长.q是因ؓ(f)所产生的COM文g没有E序D前~(Programsegmetn  profix),因ؓ(f)在DOS下所有和COM文g都有相同的程序段前缀.当DOS加蝲一个COM文g到内存中?׃(x)自动C生一份正的E序D前~.一个程序在执行的过E中,可以Ҏ(gu)需要修改其E序D前~,但是在一开?所有COM文g的程序前~都是相同?下面是程序前~的格?
    偏移位置    含义
    0000H     E序l止处理子程序地址(INT 20H)
    0002H     分配D늚l束地址,D?br />     0004H     保留
    0005H     调用DOS?a class="channel_keylink" >服务
    000AH     前一个父E序的IP和CS
    000EH     前一个父E序的CONTROL_C处理子程序地址
    0012H     前一个父E序包的g错误处理子程序地址
    0016H     保留
    002CH     环境D늚地址?br />     005EH     保留
    005CH     FCB1
    006CH `    FCB2
    0080H     命o(h)行的参数和磁盘{Ud?br /> 4.2 一个最的内存ȝE序
 上面的程序只是一个一般的DOSE序而已.q不是内存驻留的.以下是一个基本的内存ȝE序l构:
         ;Section 1
     cseg segment
      assume cs:cseg;ds:cseg
      org 100h
     start:    ;Section 2
      nop   
     done:    ;Section 3
      mov dx,offset done
      int 27h
         ;Section 4
     cseg ends
      end start
 和前一个程序相?q个E序只是增加了一个DONE部分.q个部分使用了INT 27Hq个中断调用,来终止ƈȝ在内?Terminate and Stay Resident)?使用INT 27Hq个中断调用?必须讑֮好一个指?让这个指针指向内存中可以使用的部?事实?q就相当于设|一个COM文g可加载的位置.另外DOSq提供了INT 21H,AH=31H(ȝE序,Keep process),但是使用q个中断调用?我们必须讑֮所保留的内存大?而不是设定一个指?另外q个中断调用?x)送出退出码.
 使用INT 27H?必须讑֮一个指针指向可用存储位|的开?以便让DOS用来加蝲E后执行的程?DOS本n有一个指?q个指针是加载COM文g或EXE文g时的基准地址?INT?7H ?x)改变这个指针或为新的数?同时造成新指针和旧指针之间的存储I间无法让DOS使用因此q样做会(x)造成可用存储位置愈来愈少.
 调用INT 27H时所使用的指针是个FAR指针,其中DX存放的是位移指针(Offset pointer),它可以指?4K字节之内的范?而DOS是段指针(Segment pointer),它可以指到IBM PC?40K字节的Q何一个段.在上面的例子?DS的内容不必另外设?因ؓ(f)当COM文g加蝲?DS的内容就CS的内容相同了.
 l常在编写汇~程序时,常犯的一个错误就?把assume ds:csegq个叙述误认为是,存放某一预设值到DS?事实?汇编语言E序中的Assume叙述不会(x)产生M的程序代?q个功能是告诉汇~器做某些必要的假设,以便正确地汇~程?譬如以下的程?
     cseg segment
      .............
      assume ds:cseg
      mov ah,radix
      .............
     radix db 16
      .............
     cseg ends
 上面的程序汇~时,当汇~器看到mov ah,radixq个指o(h)?它就Ҏ(gu)a(chn)ssume ds:cseg来生一定Ş式的赋值指?在面的Assume ds:cseg叙述是告诉汇~器,数据D就位于目前的代码段?q是内存ȝE序的一w要关?如果DS的内容和CS不相同时,无论是否有assume 叙述,E序执行旉?x)失?
4.3 改良的内存驻留程?br />  上面所介绍的内存驻留程序实际上没有做Q何事,只是ȝ在内存中而已.事实?在START和END之间攑օME序代码,都只?x)执行一ơ而已然后永q驻留在内存?除非是用{UL令{到START的地址?否则永q无法被使用.q要注意一?START的地址值ƈ非固定不?它会(x)Ҏ(gu)E序执行时计机的状态而改?
 下面的这个程序只是把需要驻留的E序代码装蝲?但是q不?x)执?
         ;Section 1
     cseg segment
      assume cs:cseg,ds:cseg
      org  100h
         ;Section 2
     start: 
      jmp initialize
         ;Section 3
     app_start:
      nop
     initialize:
         ;Section 4
      mov dx,offset initialize
      int  27h
         ;Section 5
     cseg ends
      end start
 上面的程序一开始执行时׃到initialize标志的地?装置好驻留在内存的应用部?原先的DONE已经Ҏ(gu)initialize,而驻留在内存的程序代码则攑֜App_Start 和Initialize之间.
 另外,你也许注意到?E序的v始地址q不是Initialize而是Start.q是因ؓ(f)所有COME序的v始地址都是100H;而上面的E序中Start是放?00H的地?如果把Initialize攑֜End之后,Initialize变成v始地址,但是q样的程序无法透过EXE2BIN转换成COM文g?如果无法产生COM文g?那么必ȝ接处理段的内?
4.4 减少内存的额外负?br />  到目前ؓ(f)?都没有接触到E序前缀,当用INT 27H?事实上是把指针以前的东西都保留在内存?q也包括了COM的程序段前缀.因ؓ(f)COM文g执行完毕?才可以把E序D前~UL.
 从上面的事实可以看出:如果E序D前~只能在COM装置E序l束后才可以Ud,那么可以由ȝ在内存中的程序代码完?要做到这一?可以把整个程序往下移?56个字?但又如何做到q一点呢?我们可以讑֮一个标?Flag),用来指示q个E序是否执行q?如果q个ȝE序或是W一ơ执行时,把整个E序往下移?56个字?以便把程序段前缀Ud.但是如果ȝE序在装|好之后,l过一D长旉仍然没有被执行时,怎么办呢?如果同时载入了好几个ȝE序?双该如何?q些重要的事情都需要用不同的E序代码来解?如果说这些程序代码超Z256字节?那么所占用的存储位|就出E序D前~所费的空?有些人用一些比较简短的代码来解册个问?但是q是比较ȝ(ch).因此对于大部分的内存ȝE序而言,除非存储I间太少,以至?56字节变得很重?否则最好不要去处理E序D前~,q样子会(x)让你的程序简z而且Ҏ(gu)阅读.
4.5 使用ȝE序
 上面介绍了如何把E序加蝲到内?q且让它永远留在内存?接下?介绍如何来用驻留在内存中的E序.
 内存ȝE序的用方法和它原先的设计有密切的关系.譬如,截获键盘输入的程序就必须通过键盘输入的Y件中?或是敲键盘所产生的硬件中断来使用.其它的驻留程序可能就必须?pȝ旉,pȝ调用,或是其它的中断才有办法?q些ȝE序必须要和以上的用方法连l?而且在驻留程序安装好之后,臛_必须建立一U用的道,否则ȝE序无法?
 IBM PC必须l由事g来驱?譬如:键盘,pȝ旉,或是软g中断.q些事g可以被截?然后Ҏ(gu)所发生的事件来执行一定的动作.因此必须让中断事件发生时,先执行我们的E序,而非pȝ的程?
 譬如,当我们设计一个截获键盘输入的ȝE序?必LȝE序和执行键盘输入的pȝ调用q结h.当DOS或是应用E序希望从键盘读取一个字W时,它就必须执行INT 16H调用.因此如果我们能够在调用INT 16H?先执行我们的ȝE序,那么ȝE序可能变成应用程序和操作pȝ间的桥梁.
 可以使用INT 21H中断调用中AH=25H来完成以上的要求.讄中断矢量可以更改INT 16H原先的中断矢量内?让它改ؓ(f)指向我们的程?譬如以下的例子所C?
     cseg segment
      assume cs:cseg,ds:cseg
      org  100h
     start: 
      jmp Initialize 
           ;Section 1
     new_keyboard_io proc far
      sti
      nop 
      iret
     new_keyboard_io endp 
           ;Section 2
     Initialize:
      mov dx,offset new_keyboard_io
      mov al,16h
      mov ah,25h
      int 21h
           ;Section 3
      mov dx,offset Initialize
      int 27h
     cseg ends
      end start
 上面的程序和4.3的程序结构是一L(fng),但是仍然有一些重要的改变.在Section 1和Section 2.在Section 1把驻留部分修Ҏ(gu)子程序Ş?Procedure),q样做是Z增加E序的可L?另外,ȝ部分多加了两个指?STI和IRET.其中STI是设|中断标?Set Interrupt Flag)和v始中?Enable interrupts).
 当CPU发生中断?它就关闭中断标志,因此CPU׃再接受中?事实?CPU?x)专心地为目前发生的中?a class="channel_keylink" >服务.当CPU停止接受中断?Mg中断的信号都?x)被忽?譬如:键盘,旉脉冲,盘Z?调制解调器的中断.如果CPU一直不接受中断,那么׃(x)漏掉一些重要的信息,计算机系l也可能因此而死?因此虽然CPU可以停止接受中断一D|?但是却不能够?
 W二个重要的指o(h)是IRET,从中断返?Return from interrupt).IRET的功能和RET极相?RET是用来从被调?的子E序中返?而IRET则是用来从中断程序返?但是使用IRETq回?它会(x)从堆栈中先取回的地址?然后再取出CPU的状态标?State Flag).CPU的状态标志在CPU接受中断??a class="channel_keylink" >自动地推入堆栈中.因此执行IRET指o(h)?CPU的状态就恢复成未中断前的状?也就是说CPU可以l接受外界的中断(CPU状态标志中断包括了中断标志).严格地说,STI和IRET在这个例子中都是多余?但是对于实际的中断处理程序而言,q两个指令都很重?
 另外,使用讄中断矢量的中断调用时,暂存器AL必须存入所要设|的中断矢量,而中断矢量指针则必须攑ֈ暂存器DS:DX?
4.6 q接中断处理E序
 若是把前一节的E序拿来执行?键盘是无法输入的,事实?处理键盘的硬件中断处理程序会(x)l箋地读取敲入的字符,q且攑ֈ{待队列?直到队列填满为止;但是׃d{待队列的Y件中断INT 16H已经被改变了,因此队列的内容就永远取不出来.
 现在写一个中断处理程?q个中断处理E序只是调用原先的键盘中断处理程?一旦做到这一点之?接下来就可以Ҏ(gu)键盘的输入做修改.以下是调用原先键盘处理E序的驻留程? 
     cseg segment
      assume cs:cseg,ds:cseg
      org  100h
     start: 
      jmp Initialize
     Old_Keyboard_IO dd ? 
;          ;Section 1
     new_keyboard_io proc far
      sti     
           ;Section 2
      pushf
      assume ds:nothing
      call  Old_Keyboard_IO
      nop 
      iret
     new_keyboard_io endp 
           ;Section 3
     Initialize:
      assume cs:cseg,ds:cseg
      mov bx,cs
      mov ds,bx
      mov al,16h
      mov ah,35h
      int 21h
      mov word ptr Old_Keyboard_IO,bx
      mov word ptr Old_Keyboard_IO[2],es
           ;End Section 3
      mov dx,offset new_keyboard_io
      mov al,16h
      mov ah,25h
      int 21h
      mov dx,offset Initialize
      int 27h
     cseg ends
      end start
 上面的程序中,W一部分是两个字(Double word),q是用来存放旧的键盘中断矢量.因ؓ(f)COM的程序都只限制在一个段?因此数据D和代码D都在同一D中.而原先的中断处理E序和我们所~写的中断处理程序未必会(x)在同一D中,所以必M用双字来储存地址?
 双字Old_Keyboard_IO可以攑֜ȝE序中的M地方;但是一般来?攑֜Jmp Initialize 之后?x)比较方?因ؓ(f)如果必须使用DEBUG来检查程序的?可以比较Ҏ(gu)调试.
 上面E序中的W二部分是驻留程序的M,其中包括了一个调用原先键盘中断处理程序的模拟中断.因ؓ(f)原先的键盘中断处理程序必M用INT的方式调?而不是用CALL的指令调?因此必须先用PUSHF把CPU状态标志压入堆栈中,然后配合上CALL来模拟INT的动?
 注意一?assume ds:nothingq一行是汇编指示,而不是程序代?它是用来告诉汇编器在产生下一行机器码?不要更会(x)目前DS的内?q样做才可以让汇~器Z一个指令生双字的地址?
 当Call Old_Keyboard_IO指o(h)执行?控制权就转移到旧的键盘中断处理程?而当q个中断调用执行完时,它就执行IRET指o(h),于是控制权又交还到目前的ȝE序.q样?不但可以让原先的键盘中断E序包ؓ(f)我们工作,同时也可以掌握控制权.如果只用IMP指o(h),跛_旧的键盘中断处理E序包去,而不把CPU状态标志推入堆栈中,那么一旦执行到IRET?q正返回到中断的状?
 上面E序中的W三部分是启动代码部?在这一部分?讑֮好新的中断矢?同时把旧的中断矢量存攑֜ȝE序代码?以便让驻留程序?
4.7 (g)查驻留程?br />  到目前ؓ(f)?已经成功地把ȝE序加在应用E序和DOS的键盘输入之?接下来可以修改输入的字符.在这一节中,我们准备截获键盘的输?q且?Y"Ҏ(gu)"y","y"Ҏ(gu)"Y".
 以下是程序代?
     cseg segment
      assume cs:cseg,ds:cseg
      org  100h
     start: 
      jmp Initialize
     Old_Keyboard_IO dd ?           
     new_keyboard_io proc far
      assume cs:cseg,ds:cseg
      sti     
           ;Section 1
      cmp ah,0
      je ki0
      assume ds:nothing
      jmp  Old_Keyboard_IO
           ;Section 2
     ki0:
      pushf
      assume  ds:nothing
      call  Old_Keyboard_IO
      cmp  al,'y'
      jne  ki1
      mov  al,'y'
      jmp  kidone
     ki1: 
      cmp  al,'Y'
      jne  kidone
      mov  al,'y'
     kidone:      
      iret
     new_keyboard_io endp 
           ;Section 3
     Initialize:
      assume cs:cseg,ds:cseg
      mov bx,cs
      mov ds,bx
      mov al,16h
      mov ah,35h
      int 21h
      mov word ptr Old_Keyboard_IO,bx
      mov word ptr Old_Keyboard_IO[2],es
           ;End Section 3
      mov dx,offset new_keyboard_io
      mov al,16h
      mov ah,25h
      int 21h
      mov dx,offset Initialize
      int 27h
     cseg ends
      end start
 在面的程序第一部分主要是检查AH是否{于0(d字符).如果AH不等?,q旧的中断处理E序来处理其它的功能:1H(d键盘状?,2H(d键盘标志).在这?使用JMP指o(h),而非使用CALL来模拟Y件中?因此原先的中断处理程序结束后,q接返回到中断前的状?
 E序的第二部分是处理AH=0H时的情Ş.首先E序中断模拟一个Y件中断来调用旧的键盘处理E序,是ؓ(f)了在d字符之后,控制权能交还到我们的ȝE序,接下来的几行E序是检查读到的字符是不?Y"?y",如果是的话就修改?
 可以借执行这个程?来验证其是否正确.除此之外,也可以证?在操作系l和应用E序之间可以加入一层控制码.q一层控制码可以先选择性地加强或取代某些DOS的功?修改l果以满x们的要求.

ThinkingTalking 2007-09-30 08:19 发表评论
]]>
վ֩ģ壺 | ΢ɽ| | Ӻ| н| | | ̨| | | ɽ| | Ҷ| ״| ̩| Դ| ʯʨ| | | ֶ| ߴ| | | | | | | Ϫ| ޶| | ¡| ڽ| | ߺ| | | | | ޳| | ±|