﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-dragon-随笔分类-汇编</title><link>http://www.cppblog.com/dragon/category/8158.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 02 Sep 2008 13:06:59 GMT</lastBuildDate><pubDate>Tue, 02 Sep 2008 13:06:59 GMT</pubDate><ttl>60</ttl><item><title>暑假看汇编的一些笔记</title><link>http://www.cppblog.com/dragon/archive/2008/09/02/60757.html</link><dc:creator>岑龙辉</dc:creator><author>岑龙辉</author><pubDate>Tue, 02 Sep 2008 12:09:00 GMT</pubDate><guid>http://www.cppblog.com/dragon/archive/2008/09/02/60757.html</guid><wfw:comment>http://www.cppblog.com/dragon/comments/60757.html</wfw:comment><comments>http://www.cppblog.com/dragon/archive/2008/09/02/60757.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/dragon/comments/commentRss/60757.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/dragon/services/trackbacks/60757.html</trackback:ping><description><![CDATA[<p>在汇编源程序中,数据不能以字母开头,故要加0识别!</p>
<p>debug程序开始时DS指向的是PSP的头地址,而CS=DS+10H</p>
<p>不能将一个数值直接送入段寄存器,要通过其它寄存器进行传送!</p>
<p>(N/16+1)*16 意思是总取多16个字节存放多出的字节.N+16不等价左边的式子.<br>它等价于(int(N/16)+1).</p>
<p>一般来说,当我们要暂存数据时,都应该使用栈!</p>
<p>(1)只有bx,si,di,bp用在[]里进行内在单元的存取.<br>(2)bx,si,di,bp只能以bx与si,bx与di,bp与si,bp与di四种组合出现<br>形像些:<br>&nbsp;&nbsp;&nbsp; si<br>&nbsp; /<br>bx<br>&nbsp; \ <br>&nbsp;&nbsp;&nbsp; di</p>
<p>&nbsp;&nbsp;&nbsp; si<br>&nbsp; /<br>bp<br>&nbsp; \ <br>&nbsp;&nbsp;&nbsp; di<br>(3)只要在[]中使用寄存器bp,而指令中没有显性地给出段地址,段地址就默认在ss中,其它的&nbsp;&nbsp;&nbsp; 是不是默认存放在ds中?</p>
<p>数据处理的分类:写入,读取,运算!<br>数据存在的三个地方:CPU内,内存,端口!</p>
<p>push只进行字操作,pop呢?</p>
<p><br>用dd定义的数的存放,如100001它的十六进制为186A1H,则它在内存的存放形式是<br>A1 86 01 00 <br>刚刚好是32位,和我们的逻辑000186A1不一样(规律:倒过来).<br>在一个数据段里定义的数据是连续存放的,但要看清楚它们是什么类型(dd,dw,db).</p>
<p><br>db '1634'里面一个字符占一个字节,保存的是相应的ACSII码.</p>
<p>&nbsp;</p>
<p>loop指令是先把CX寄存器的值减1然后再判断是否是0</p>
<p>&nbsp;</p>
<p>assume cs:code<br>code segment<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov ax,4c00H<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int 21H<br>start: mov ax,0<br>&nbsp;&nbsp;&nbsp; s: nop<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nop</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov di,offset s&nbsp;&nbsp;&nbsp;&nbsp; ;以下四行复制s2的第一条指令给s<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov si,offset s2&nbsp;&nbsp;&nbsp; ;刚刚好覆盖了s的两条nop指令<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov ax,cs:[si]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;复制过去的内容是:"向前或向后移动多少"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov cs:[di],ax</p>
<p>&nbsp;&nbsp; s0: jmp short s<br>&nbsp;&nbsp; s1: mov ax,0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int 21H<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov ax,0</p>
<p>&nbsp;&nbsp; s2: jmp short s1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;机器码EBF6;意思是"向前移动10d个字节"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nop<br>code ends<br>end start</p>
<p>;9D:0000 B8004C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; AX,4C00<br>;9D:0003 CD21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INT&nbsp;&nbsp;&nbsp;&nbsp; 21<br>;9D:0005 B80000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; AX,0000<br>;9D:0008 EBF6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JMP&nbsp;&nbsp;&nbsp;&nbsp; 0000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EBF6复制过来后前移10个字节即跳到0000<br>;9D:000A BF0800&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; DI,0008<br>;9D:000D BE2000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; SI,0020<br>;9D:0010 2E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CS:<br>;9D:0011 8B04&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; AX,[SI]<br>;9D:0013 2E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CS:<br>;9D:0014 8905&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; [DI],AX<br>;9D:0016 EBF0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JMP&nbsp;&nbsp;&nbsp;&nbsp; 0008<br>;9D:0018 B80000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; AX,0000<br>;9D:001B CD21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INT&nbsp;&nbsp;&nbsp;&nbsp; 21<br>;9D:001D B80000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; AX,0000</p>
<p>对call指令的一些理解:<br>call word ptr 内存单元地址<br>书上理解:<br>push IP<br>jmp word ptr 内存单元地址<br>我的理解:<br>(1)IP的值先变成CALL指令后的第一个字节的偏移地址，然后才被压入栈;<br>(2)压入后再改变IP的值,即(IP)=内存单元地址的值.</p>
<p><br>call dword ptr 内存单元地址<br>书上理解:<br>push cs<br>push ip<br>jmp dword ptr 内存单元地址</p>
<p>开始是将此时的CS,IP(IP应该是CALL命令后的第一个字节)压入栈,CS是先压入钱的,<br>然后跳到内存单元中内容所指的地址,<br>即CS=((内存单元地址)+2),IP=(内存单元)//其实这两个是JMP指令的理解.</p>
<p>&nbsp;</p>
<p><br>对X/N=int(H/N)*65536+(rem(H/N)*65536+L)/N的理解<br>int(H/N)*65536求出的是高16位的值,即 16位的值0000<br>后面16位是低16位的值,因为后面的商不会超过16位,求出的商就是低16的值,加到0000上<br>而(rem(H/N)*65536+L)/N算得的余数就是本X/N的余数.<br>注意*65536的含义是向左移多少位,后面的补零.</p>
<p>&nbsp;</p>
<p>先算16进制再算十进制!</p>
<p>&nbsp;</p>
<p>int是将子程序装入内在先,然后通过代号进行调用.(静态)<br>而call就如动态执行这样,等到运行时才装入内存.(动态)</p>
<p><br>P246的中断例程的理解<br>lp:push bp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;此时栈里的情况是:bp ip cs 标志寄存器<br>&nbsp;&nbsp; mov bp,sp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp; dec cx<br>&nbsp;&nbsp; jcxz lpret<br>&nbsp;&nbsp; add [bp+2],bx&nbsp;&nbsp; ;因为bp默认的段寄存器是ss,故使用了bp,而+2就指向了ip的值.<br>lpret:<br>&nbsp;&nbsp; pop bp<br>&nbsp;&nbsp; iret&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;由cx 来决定是循环还是向下继续执行,</p>
<p>&nbsp;</p>
<p><br>编写中断例程的步聚:<br>(1)先将代码复制到指定的位置,注意这里要指出要复制字节的长度<br>(2)再把指定的代码存放位置放到向量表中,因为是通过向量表进行访问的.<br>(3)你可以编写你的中断例程了!记得开始与结尾标志!</p>
<p>&nbsp;</p>
<p>在in与out指令中,只能使用ax或al来存放从端口中读入的数据或要发送到端口中的数据,访问8位端口时用AL,访问16位端口时要用AX.</p>
<p>shl,shr指令移位多于一位时一定要将移的位数放在cl里.</p>
<p>BCD码4位确定一个数,如26的BCD码为0010 0110</p>
<p>&nbsp;</p>
<p>7.8&nbsp; 已知对应于中断类型码为18H的中断服务程序存放在0020H：6314H开始的内存区域中，求对应于18H类型码的中断向量存放位置和内容。</p>
<p>在编写程序时，为什么通常总要用STI和CLI中断指令来设置中断允许标志？8259A的中断屏蔽寄存器IMR和中断允许标志IF有什么区别？</p>
<p>【解答】偏移地址EA=18H&#215;4=60H，18H中断向量在中断向量表中的入口地址为00000H＋60H=00060H。中断服务程序存放在0020H：6314H开始的内存区域中，所以（00060H）=0020H，（00061H）= 6314H。</p>
<p>IF是8086微处理器内部标志寄存器Flags的中断允许标志位。若IF=1，则CPU可以接受中断请求；若IF=0，8086就不接受外部可屏蔽中断请求INTR引线上的请求信号。在编写程序时，用STI指令使中断允许标志位IF=1，目的是使CPU能够接受中断请求，或实现中断嵌套。而用CLI指令使中断允许标志位IF=0，则可以关中断，使CPU拒绝接受外部中断请求信号。</p>
<p>如果8259A的中断屏蔽寄存器IMR中的某位为1，就把这一位对应的中断请求输入信号IR屏蔽掉，无法被8259A处理，也无法向8086处理器产生INTR请求。</p>
<p><br>注意:在后面加有":"的地址标号,只能在代码段中使用,不能在其他段中使用.</p>
<p>$表示的是本行地址,<br>$$则表示开始汇编的地址.</p>
<p>&nbsp;</p>
<p>2.3总结:<br>执行mov指令不改变CS寄存器<br>执行jmp 段地址:偏移地址&nbsp;&nbsp; 改变CS和IP<br>执行jmp 寄存器&nbsp;&nbsp; 只改变IP不改变CS</p>
<p>&nbsp;</p>
<p><br>实验五总结:<br>还没加载程序前:<br>CS:IP指向程序段的第一条指令,故CS可以知道.<br>SS=CS-2<br>DS=SS-10H ;这个知道有没有用?</p>
<p>加载后:<br>SS=CS-1;<br>DS=CS-2;</p>
<img src ="http://www.cppblog.com/dragon/aggbug/60757.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/dragon/" target="_blank">岑龙辉</a> 2008-09-02 20:09 <a href="http://www.cppblog.com/dragon/archive/2008/09/02/60757.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>