你老豆 發表於 2019-7-23 20:27:00

第三章 汇编语言基础

<div id="gAnDyoPoPuP" style="display: none; top: 9598.2px; left: -30px">
<div style="min-width: 57px; min-height: 19px; padding: 3.8px; border-radius: 6.33333px"><img style="height: 19px; width: 19px" title="Google Translate" alt="Google Translate"><img style="height: 19px; width: 19px" title="GTranslateWinS Options" alt="GTranslateWinS Options"></div>
</div>
<div id="gAnDyoPoPuP" style="display: flex; top: 2981.4px; left: 7px">
<div style="min-width: 57px; min-height: 19px; padding: 3.8px; border-radius: 6.33333px"><img style="height: 19px; width: 19px" title="Google Translate" alt="Google Translate"><img style="height: 19px; width: 19px" title="GTranslateWinS Options" alt="GTranslateWinS Options"></div>
</div>
<div id="gAnDyoPoPuP" style="display: none; top: 2753.6px; left: 239px">
<div style="min-width: 57px; min-height: 19px; padding: 3.8px; border-radius: 6.33333px"><img style="height: 19px; width: 19px" title="Google Translate" alt="Google Translate"><img style="height: 19px; width: 19px" title="GTranslateWinS Options" alt="GTranslateWinS Options"></div>
</div>
<div id="gAnDyoPoPuP" style="display: none; top: 1704px; left: -52px">
<div style="min-width: 57px; min-height: 19px; padding: 3.8px; border-radius: 6.33333px"><img style="height: 19px; width: 19px" title="Google Translate" alt="Google Translate"><img style="height: 19px; width: 19px" title="GTranslateWinS Options" alt="GTranslateWinS Options"></div>
</div>
<h2><span style="font-family: 宋体">3.1 汇编语言的基本元素</span></h2>
<h3><span style="font-family: 宋体">3.1.1 整数常量</span></h3>
<p><span style="font-family: 宋体">&nbsp; 整数常量由符号(可选)开头,加上一个或多个数字及一个表示数制基数的字符构成:</span></p>
<p><span style="font-family: 宋体">  </span></p>
<div class="cnblogs_code">
<pre>[{+|-}] digits </pre>
</div>
<p><span style="font-family: 宋体">&nbsp; 本章全部使用微软的语法格式符号,[...]中的参数可选,{..}内参数要求从多个括起的采纳数中选择一个(由|分隔)。</span></p>
<p><span style="font-family: 宋体">&nbsp; Radix(基数后缀)可为下列之一(不区分大小写):</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">h   十六进制
q/o八进制
d    十进制
b    二进制
r    编码实数
t    十进制(可选)
y    二进制(可选)</span></pre>
</div>
<p><span style="font-family: 宋体">&nbsp; 若整数常量后无后缀,则默认为十进制,以字母开头的十六进制必须加0,以防止汇编编译器将其解释为标识符。</span></p>
<h3><span style="font-family: 宋体">3.1.2 整数表达式</span></h3>
<p><span style="font-family: 宋体">&nbsp; 整数表达式是包含整数值和算术运算符的数学表达式,整数表达式计算的结果必须是能够存储在32位整数内的。如下:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">运算符         名称          优先级
()         圆括号          </span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">
+, -          单目加、减       </span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">
*, /          乘、除          </span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">
MOD         取模            </span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">
+, -          加、减          </span><span style="color: rgba(128, 0, 128, 1)">5</span></pre>
</div>
<h3><span style="font-family: 宋体">3.1.3 实数常量</span></h3>
<p><span style="font-family: 宋体">&nbsp; 有两种类型的实数常量:十进制实数和编码(十六进制)实数。</span></p>
<p><span style="font-family: 宋体">&nbsp; <strong>十进制实数</strong>由符号位、整数部分、小数点、表示小数的整数和指数部分组成:</span></p>
<div class="cnblogs_code">
<pre>integer.</pre>
</div>
<p><span style="font-family: 宋体">&nbsp; 符号位和指数的描述如下:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">sign         {+, -}
exponentE[{+, -}]integer</span></pre>
</div>
<p><span style="font-family: 宋体">&nbsp; 实数常量中应该至少有一个数字和一个小数点。</span></p>
<p><span style="font-family: 宋体">&nbsp; <strong>编码实数</strong> 如果准确的知道数字的二进制表示,就可以使用十六进制指定编码实数常量。(IEEE实数格式的讨论在第17章)</span></p>
<h3><span style="font-family: 宋体">3.1.4 字符常量</span></h3>
<p><span style="font-family: 宋体">&nbsp; 字符常量时以单引号或双引号引起的单个字符。汇编编译器将其转换为与字符对应的二进制ASCII码。</span></p>
<h3><span style="font-family: 宋体">3.1.5 字符串常量</span></h3>
<p><span style="font-family: 宋体">&nbsp; 字符串常量以单引号或双引号引起的一串字符:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">ABC</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">X</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Goodnight, Gracie</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">4096</span><span style="color: rgba(128, 0, 0, 1)">'</span>

<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Say "Goodnight, " Gracie</span><span style="color: rgba(128, 0, 0, 1)">'</span></pre>
</div>
<h3><span style="font-family: 宋体">3.1.6 保留字</span></h3>
<p><span style="font-family: 宋体">&nbsp; 保留字可以是下列之一:</span></p>
<p><span style="font-family: 宋体">&nbsp; * 指令助记符, 如 MOV、ADD、MUL</span></p>
<p><span style="font-family: 宋体">&nbsp; * 伪指令, 用于告诉MASM如何编译</span></p>
<p><span style="font-family: 宋体">&nbsp; * 属性, 用于为变量和操作数提供有关尺寸以及使用方式的信息, 如 BYTE和WORD</span></p>
<p><span style="font-family: 宋体">&nbsp; * 运算符, 用在常量表达式中</span></p>
<p><span style="font-family: 宋体">&nbsp; * 预定义符号, 如@data, 在编译时返回整数常量值</span></p>
<p><span style="font-family: 宋体">&nbsp; 完整的MASM保留字见附录D</span></p>
<h3><span style="font-family: 宋体">3.1.7 标识符</span></h3>
<p><span style="font-family: 宋体">&nbsp; 标识符是程序员使用的名字,用来识别变量、常量、过程或代码标号。</span></p>
<p><span style="font-family: 宋体">&nbsp; * 可包含1-247个字符<br></span></p>
<p><span style="font-family: 宋体">&nbsp; * 大小写不敏感</span></p>
<p><span style="font-family: 宋体">&nbsp; * 第一个字符必须是字母、下划线、@或$, 后续字符可为数字</span></p>
<p><span style="font-family: 宋体">&nbsp; * 标识符不能与汇编编译器的保留字相同</span></p>
<p><span style="font-family: 宋体">&nbsp; 运行汇编编译器时, 通过在命令行加-Cp可使关键字和标识符大小写敏感。</span></p>
<p><span style="font-family: 宋体">&nbsp; 尽量避免使用@开头的标识符,因为@符号被编译器扩展用于预定义的符号。</span></p>
<h3><span style="font-family: 宋体">3.1.8 伪指令</span></h3>
<p><span style="font-family: 宋体">&nbsp; 伪指令时程序源代码被编译时由编译器识别和执行的命令, 不同编译器不同。如:</span></p>
<p><span style="font-family: 宋体">&nbsp; .DATA 伪指令标识了程序中包含变量的区域</span></p>
<p><span style="font-family: 宋体">&nbsp; .CODE 伪指令标识了程序中包含指令的区域</span></p>
<p><span style="font-family: 宋体">&nbsp; PROC 伪指令标识过程的开始</span></p>
<p><span style="font-family: 宋体">&nbsp; 附录D包含MASM伪指令和运算符的完整参考手册。</span></p>
<h3><span style="font-family: 宋体">3.1.9 指令</span></h3>
<p><span style="font-family: 宋体">&nbsp; 指令是在程序被加载至内存并且开始运行后, 在运行期间由处理器执行的语句, 一条语句包含四个基本部分: </span></p>
<p><span style="font-family: 宋体">&nbsp; * 标号(可选)</span></p>
<p><span style="font-family: 宋体">&nbsp; * 指令助记符(必须)</span></p>
<p><span style="font-family: 宋体">&nbsp; * 操作数(通常需要)</span></p>
<p><span style="font-family: 宋体">&nbsp; * 注释(可选)</span></p>
<p><span style="font-family: 宋体">&nbsp; 源代码行可以只包含标号和注释, 下面显示了指令的标准格式: </span></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>标号: 指令助记符 操作数 ; 注释</pre>
</div>
<p>&nbsp;</p>
<h4><span style="font-family: 宋体">3.1.9.1 标号</span></h4>
<p><span style="font-family: 宋体">&nbsp; 标号是充当指令或数据位置标记的标识符。</span></p>
<p><span style="font-family: 宋体"><strong>&nbsp; 代码标号</strong> 程序代码区中的标号必须以冒号(:)结尾, 在此位置, 代码标号通常用作跳转和循环指令的目标地址。代码标号可以和指令在同一行, 也可以独自成行。</span></p>
<p><span style="font-family: 宋体"><strong>&nbsp; 数据标号</strong> 不必使用冒号(:)结尾。</span></p>
<h4><span style="font-family: 宋体">3.1.9.2 指令助记符、操作数、注释</span></h4>
<p><span style="font-family: 宋体">&nbsp; 注释可使用以下两种方法指定:</span></p>
<p><span style="font-family: 宋体">&nbsp; * 单行注释: 以分号(;)开始, 之后所有字符视为注释</span></p>
<p><span style="font-family: 宋体">&nbsp; * 块注释: 以COMMENT 伪指令<span style="font-family: 宋体">及一个用户自定义的符号</span>开始, 之后直到再次相同自定义符号出现之间的字符视为注释。</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2><span style="font-family: 宋体">3.2 例子: 三个整数相加</span></h2>
<h3><span style="font-family: 宋体">3.2.1 程序清单</span></h3>
<div class="cnblogs_code">
<pre>TITLE <span style="color: rgba(0, 0, 255, 1)">Add</span> <span style="color: rgba(0, 0, 255, 1)">and</span> Subtract   (<span style="color: rgba(0, 0, 255, 1)">Add</span><span style="color: rgba(0, 0, 0, 1)">.asm)
</span><span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> This program ads and substracts 32-bit integers</span>
INCLUDE Irvine32.<span style="color: rgba(0, 0, 255, 1)">inc</span><span style="color: rgba(0, 0, 0, 1)">
.code
main PROC
    </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> eax, 10000H
    </span><span style="color: rgba(0, 0, 255, 1)">add</span><span style="color: rgba(0, 0, 0, 1)"> eax, 40000H
    </span><span style="color: rgba(0, 0, 255, 1)">sub</span><span style="color: rgba(0, 0, 0, 1)"> eax, 20000H
    </span><span style="color: rgba(0, 0, 255, 1)">call</span><span style="color: rgba(0, 0, 0, 1)"> DumpRegs
    exit
main ENDP
END main</span></pre>
</div>
<p>&nbsp;</p>
<h3><span style="font-family: 宋体">3.2.3 程序说明</span></h3>
<p><span style="font-family: 宋体">&nbsp; TITLE 伪指令将整行标为注释。</span></p>
<p><span style="font-family: 宋体">&nbsp; ;将之后的整行字符标为注释。</span></p>
<p><span style="font-family: 宋体">&nbsp; INCLUDE 伪指令从Irvine32.inc文件中拷贝必须的定义和设置信息。</span></p>
<p><span style="font-family: 宋体">&nbsp; .code 伪指令用来标记代码段的开始</span></p>
<p><span style="font-family: 宋体">&nbsp; main PROC: PROC伪指令用来标识子程序的开始, 名称为main</span></p>
<p><span style="font-family: 宋体">&nbsp; call DumpRegs: CALL指令调用一个显示CPU寄存器值得子程序。</span></p>
<p><span style="font-family: 宋体">&nbsp; exit 表达式(间接)调用预定义的MS-Windows函数来终止程序。<br></span></p>
<p><span style="font-family: 宋体">&nbsp; main ENDP: ENDP伪指令表明该行时汇编源程序的最后一行, 编译器将忽略该行之后又的所有内容, 其后的标识符main是程序启动过程(程序启动时执行的子程序)的名字。</span></p>
<p><span style="font-family: 宋体">&nbsp; <strong>段 </strong>程序是以段组织的, 常见的段有代码段。数据段和堆栈段等。代码段包含程序的全部可执行指令, 通常代码段中都有一个或一个以上的过程, 其中一个是启动过程。堆栈段存放着子程序的参数和局部变量, 数据段则存放着变量。</span></p>
<h4><span style="font-family: 宋体">3.2.3.1 AddSub的另一个版本</span></h4>
<p><span style="font-family: 宋体">&nbsp; 上一个程序隐藏了许多细节。</span></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>TITLE <span style="color: rgba(0, 0, 255, 1)">Add</span> <span style="color: rgba(0, 0, 255, 1)">and</span><span style="color: rgba(0, 0, 0, 1)"> Substract
.</span><span style="color: rgba(128, 0, 128, 1)">386</span><span style="color: rgba(0, 0, 0, 1)">
.MODEL flat, stdcall
.STACK </span><span style="color: rgba(128, 0, 128, 1)">4096</span><span style="color: rgba(0, 0, 0, 1)">
ExitProcess PROTO, </span><span style="color: rgba(0, 128, 128, 1)">dwExitCode:</span><span style="color: rgba(0, 0, 0, 1)">DWORD
DumpRegs PROTO

.code
main PROC
    </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> eax, 10000H
    </span><span style="color: rgba(0, 0, 255, 1)">add</span><span style="color: rgba(0, 0, 0, 1)"> eax, 40000H
    </span><span style="color: rgba(0, 0, 255, 1)">sub</span><span style="color: rgba(0, 0, 0, 1)"> eax, 20000H
    </span><span style="color: rgba(0, 0, 255, 1)">call</span><span style="color: rgba(0, 0, 0, 1)"> DumpRegs

    INVOKE ExitProcess, </span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">
main ENDP
END main</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">&nbsp; .386指出来该程序要求的最低CPU(Intel 386)</span></p>
<p><span style="font-family: 宋体">&nbsp; .MODEL flat, stdcall: 为保护模式生成代码, STDCALL允许调用MS-WIndows函数。</span></p>
<p><span style="font-family: 宋体">&nbsp; PROTO伪指令声明了该程序使用的子程序。</span></p>
<p><span style="font-family: 宋体">&nbsp; INVOKE 是一个用于调用过程或函数的汇编伪指令。<br></span></p>
<p>&nbsp;</p>
<h2><span style="font-family: 宋体">3.4 定义数据</span></h2>
<h3><span style="font-family: 宋体">3.4.1 内部数据类型</span></h3>
<p><span style="font-family: 宋体"><img src="https://img2018.cnblogs.com/blog/1374196/201907/1374196-20190723192042573-612512726.jpg" alt=""></span></p>
<h3>&nbsp;<span style="font-family: 宋体">3.4.2 数据定义语句</span></h3>
<p><span style="font-family: 宋体">&nbsp; 数据定义语句为变量在内存中保留存储空间并且可以为变量指定名称。</span></p>
<div class="cnblogs_code">
<pre>[名称] 数据定义伪指令 初始值 [, 初始值 ...]</pre>
</div>
<p><span style="font-family: 宋体">&nbsp; 初始值 数据定义语句中至少要有一个初始值或"?"符号, "?"在不想给数据赋予任何特定值的时候使用。</span></p>
<h3><span style="font-family: 宋体">2.4.3 定义BYTE、SBYTE、WORD、SWORD、DWORD、SWORD/.QWORD、TBYTE、实数数据</span></h3>
<p><span style="font-family: 宋体">&nbsp; BYTE(无符号字节)和SBYTE(有符号字节)伪指令为一个或多个有符号及无符号字节分配空间, 每个初始值必须是8位的整数表达式或字符常量。</span></p>
<div class="cnblogs_code">
<pre>value1 BYTE <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">A</span><span style="color: rgba(128, 0, 0, 1)">'</span>         <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 字符常量</span>
value2 BYTE <span style="color: rgba(128, 0, 128, 1)">0</span>             <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 最小无符号字节常量</span>
value3 BYTE <span style="color: rgba(128, 0, 128, 1)">255</span>         <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 最大无符号字节常量</span>
value4 SBYTE -<span style="color: rgba(128, 0, 128, 1)">128</span>         <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 最小有符号字节常量</span>
value5 SBYTE +<span style="color: rgba(128, 0, 128, 1)">127</span>         <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 最大有符号字节常量</span>
<span style="color: rgba(0, 0, 0, 1)">value6 BYTE ?
value7 DB </span><span style="color: rgba(128, 0, 128, 1)">255</span><span style="color: rgba(0, 0, 0, 1)">
value8 DB -</span><span style="color: rgba(128, 0, 128, 1)">128<br><span style="color: rgba(0, 0, 0, 1)">list1 BYTE <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(128, 0, 128, 1)">10, 20, 30, 40<span style="color: rgba(0, 128, 0, 1)">;<span style="color: rgba(0, 128, 0, 1)"> 偏移从左到右增大<br></span></span></span></span>list2 BYTE <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(128, 0, 128, 1)">10, 20, 30, 40<br>      <span style="color: rgba(128, 0, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">BYTE <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(128, 0, 128, 1)">60, 70, 80, 90<br>      <span style="color: rgba(128, 0, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">BYTE <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(128, 0, 128, 1)">11, 22, 33, 44<br></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<pre><span style="color: rgba(128, 0, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">list3 BYTE <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(128, 0, 128, 1)">10, 20, 41H, 00100010b<br></span></span>list4 BYTE <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(128, 0, 128, 1)">0AH, 20H, 'A', 22H<br></span></span></span></span></pre>
<pre><span style="color: rgba(128, 0, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">string1 BYTE <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(128, 0, 128, 1)">'Hello, World !', 0<br>      <span style="color: rgba(128, 0, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">BYTE <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(128, 0, 128, 1)">"send me a message", </span></span></span></span>0DH, 0AH, 0      ; 回车换行<br></span></span>string2 \<br>      BYTE <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(128, 0, 128, 1)">0AH, 20H, 'A', 22H</span></span></span></span></pre>
</div>
<p>&nbsp;&nbsp; <span style="font-family: 宋体"><strong>变量名</strong> 变量名是一个标号, 表示变量相对于其所在段开始的偏移, value2的偏移值为1</span></p>
<p><span style="font-family: 宋体">&nbsp;<strong>DUP操作符</strong> DUP操作符使用一个常量表达式作为计数器来重复分配空间</span></p>
<div class="cnblogs_code">
<pre>BYTE <span style="color: rgba(128, 0, 128, 1)">20</span> DUP(<span style="color: rgba(128, 0, 128, 1)">0</span>)      <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 20字节, 全部初始化为0</span>
BYTE <span style="color: rgba(128, 0, 128, 1)">20</span> DUP(?)         <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 20字节, 未初始化</span>
BYTE <span style="color: rgba(128, 0, 128, 1)">4</span>DUP(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">STACK</span><span style="color: rgba(128, 0, 0, 1)">"</span>) <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 20字节, "STACKSTACKSTACKSTACK</span></pre>
</div>
<p><span style="font-family: 宋体">&nbsp; WORD(字)、SWORD(有符号字)分配16位存储空间, 老版本编译器使用DW。</span></p>
<p><span style="font-family: 宋体">&nbsp; DWORD(双字)、SDWORD(有符号双字)分配32位存储空间, DD</span></p>
<p><span style="font-family: 宋体">&nbsp; QWORD(四节)分配8字节空间, DQ</span></p>
<p><span style="font-family: 宋体">&nbsp; TBYTE(五字)分配10字节空间, DT</span></p>
<p><span style="font-family: 宋体">&nbsp; REAL4定义4字节单精度实数</span></p>
<p><span style="font-family: 宋体">&nbsp; REAL8定义8字节双精度实数</span></p>
<p><span style="font-family: 宋体">&nbsp; REAL10定义扩展精度实数</span></p>
<p><span style="font-family: 宋体"><img src="https://img2018.cnblogs.com/blog/1374196/201907/1374196-20190723194441577-1916188980.jpg" alt=""></span></p>
<h3><span style="font-family: 宋体">3.4.9 小尾顺序</span></h3>
<p><span style="font-family: 宋体">&nbsp; Intel处理器使用小尾顺序(little endian order)的方案存取内存数据, 其含义即变量的最低有效字节存储在地址最小的地址单元中, 其余字节按顺序存储。</span></p>
<p><span style="font-family: 宋体">&nbsp; 双字12345678H(305419896D)的存储:</span></p>
<p><span style="font-family: 宋体"><img src="https://img2018.cnblogs.com/blog/1374196/201907/1374196-20190723194809477-101294962.jpg" alt=""></span></p>
<p><img src="https://img2018.cnblogs.com/blog/1374196/201907/1374196-20190723194816389-260091245.jpg" alt=""></p>
<h3><span style="font-family: 宋体">3.4.10 位AddSub程序添加变量</span></h3>
<div class="cnblogs_code">
<pre>TITLE <span style="color: rgba(0, 0, 255, 1)">Add</span> <span style="color: rgba(0, 0, 255, 1)">and</span><span style="color: rgba(0, 0, 0, 1)"> Substract         (AddSub.asm)
</span><span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> This programs adds and substracts 32-bit integers.</span>
INCLUDE Irvine32.<span style="color: rgba(0, 0, 255, 1)">inc</span><span style="color: rgba(0, 0, 0, 1)">

.data
val1 DWORD 10000H
val2 DWORD 40000H
val3 DWORD 20000H
finalVal DWORD ?

.code
main PROC
    </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> eax, val1    ; 注意得到的不是偏移量
    </span><span style="color: rgba(0, 0, 255, 1)">add</span><span style="color: rgba(0, 0, 0, 1)"> eax, val2
    </span><span style="color: rgba(0, 0, 255, 1)">sub</span><span style="color: rgba(0, 0, 0, 1)"> eax, val3
    </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> finalVal, eax
    </span><span style="color: rgba(0, 0, 255, 1)">call</span><span style="color: rgba(0, 0, 0, 1)"> DumpRegs
   
    exit
main ENDP
END main</span></pre>
</div>
<h3><span style="font-family: 宋体">3.4.11 未初始化数据的声明</span></h3>
<p><span style="font-family: 宋体">&nbsp; ".DATA?"伪指令可用于声明未初始化的数据, "DATA?"在定义大块的未初始化数据时非常有用, 因为它可以缩小编译后的程序尺寸:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">.data
smallArray DWORD </span><span style="color: rgba(128, 0, 128, 1)">10</span> DUP(<span style="color: rgba(128, 0, 128, 1)">0</span>)      <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 40bytes</span>
<span style="color: rgba(0, 0, 0, 1)">.data?
bigArray DWORD </span><span style="color: rgba(128, 0, 128, 1)">5000</span> DUP(?)      <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 2000bytes</span></pre>
</div>
<p><span style="font-family: 宋体">&nbsp; 下面的代码将生成大于20000字节的程序:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">.data
smallArray DWORD </span><span style="color: rgba(128, 0, 128, 1)">10</span> DUP(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
bigArray DWORD </span><span style="color: rgba(128, 0, 128, 1)">5000</span> DUP(?)</pre>
</div>
<p><span style="font-family: 宋体">&nbsp; 混合代码和数据 汇编编译器允许程序在代码和数据之间来回切换, 在定义仅在局部程序中使用的变量非常方便:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">.code
</span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> eax, ebx
.data
temp DWORD ?
</span><span style="color: rgba(0, 0, 255, 1)">mov</span> eax, temp</pre>
</div>
<p><span style="font-family: 宋体">&nbsp; 编译器将temp和其他变量一起放到了数据段中, 对于同一代码文件中的每条指令来说, temp变量都可见。</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2><span style="font-family: 宋体">3.5 符号常量</span></h2>
<p><span style="font-family: 宋体">&nbsp; 符号常量(符号定义)通过将标识符与整数表达式或文本联系起来而创建的, 不占用存储空间, 仅在编译时使用, 不可在运行期间改变, 类似C语言的预定义常量(#define)。</span></p>
<h3><span style="font-family: 宋体">3.5.1 等号伪指令</span></h3>
<p><span style="font-family: 宋体">&nbsp; 等号伪指令将符号名和整数表达式联系起来:</span></p>
<div class="cnblogs_code">
<pre>名字 = 表达式</pre>
</div>
<p><span style="font-family: 宋体">&nbsp; 如:</span></p>
<div class="cnblogs_code">
<pre>COUNT= <span style="color: rgba(128, 0, 128, 1)">500</span>
<span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> al, COUNT

</span><span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 编译器编译生成</span>

<span style="color: rgba(0, 0, 255, 1)">mov</span> al, <span style="color: rgba(128, 0, 128, 1)">500</span></pre>
</div>
<p><span style="font-family: 宋体">&nbsp; 也可使用在DUP中作为定义的数据数量。</span></p>
<p><span style="font-family: 宋体">&nbsp; 以"="<span style="font-family: 宋体">重复定义定义的符号可重定义多次, 按照源代码的书写顺序由编译器改变其值。</span></span></p>
<h3><span style="font-family: 宋体"><span style="font-family: 宋体">2.5.2 计算数组和字符串的大小</span></span></h3>
<p><span style="font-family: 宋体"><span style="font-family: 宋体">&nbsp; MASM使用$运算符(当前地址计数器)返回当前程序语句的地址偏移:</span></span></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>list BYTE <span style="color: rgba(128, 0, 128, 1)">10</span>, <span style="color: rgba(128, 0, 128, 1)">20</span>, <span style="color: rgba(128, 0, 128, 1)">30</span>, <span style="color: rgba(128, 0, 128, 1)">40</span><span style="color: rgba(0, 0, 0, 1)">
listSize = ($ - list)</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">&nbsp; 字数组需要 / 2, 双字等数组类似<br></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">list WORD 1000H, 2000H, 3000H, 4000H
listSize = ($ - list) / </span><span style="color: rgba(128, 0, 128, 1)">2</span></pre>
</div>
<p>&nbsp;</p>
<h3><span style="font-family: 宋体">3.5.3 EQU伪指令</span></h3>
<p><span style="font-family: 宋体">&nbsp; EQU伪指令将符号名和整数表达式或任意文本联系起来: </span></p>
<div class="cnblogs_code">
<pre>name EQU expression         <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> expression必须是有效的整数表达式</span>
name EQU sybol                  <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> sybol必须是已经使用"="或EQU定义的符号名</span>
name EQU &lt;text&gt;                <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> text字符串必须置于尖括号内</span></pre>
</div>
<p><span style="font-family: 宋体"></span></p>
<div class="cnblogs_code">
<pre>PI EQU &lt;<span style="color: rgba(128, 0, 128, 1)">3</span>.<span style="color: rgba(128, 0, 128, 1)">14159</span><span style="color: rgba(0, 0, 0, 1)">&gt;
pressKey EQU &lt;</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Press any key to continue ...</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">&gt;

.data
prompt BYTE pressKey</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-family: 宋体"></span></p>
<div class="cnblogs_code">
<pre>matrix1 EQU <span style="color: rgba(128, 0, 128, 1)">10</span> * <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">
matrix2 EQU &lt;</span><span style="color: rgba(128, 0, 128, 1)">10</span> * <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">&gt;

.data
M1 WORD matrix1
M2 WORD matrix2

</span><span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 编译器处理为</span>
<span style="color: rgba(0, 0, 0, 1)">
M1 WORD </span><span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">
M2 WORD </span><span style="color: rgba(128, 0, 128, 1)">10</span> * <span style="color: rgba(128, 0, 128, 1)">10</span></pre>
</div>
<p><span style="font-family: 宋体">&nbsp; <strong>不允许重定义</strong> 与"="伪指令不同, 使用EQU定义的符号不能再同一源码文件中重复定义</span></p>
<h3><span style="font-family: 宋体">2.5.4 TEXTEQU伪指令</span></h3>
<p><span style="font-family: 宋体">&nbsp; TEXTEQU与EQU非常相似, 可用于创建文本宏(text macro):</span></p>
<div class="cnblogs_code">
<pre>name TEXTEQU &lt;text&gt;               <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 将文本赋予符号</span>
name TEXTEQU textmacro         <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 将已定义的文本宏内容赋予符号</span>
name TEXTEQU %constExpr         <span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> 将整数表达式常量赋予符号</span></pre>
</div>
<div class="cnblogs_code">
<pre>rowSize = <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">
count TEXTEQU %(rowSize * </span><span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">)
move TEXTEQU &lt;</span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)">&gt;
setupAL TEXTEQU &lt;move al, count&gt;</span></pre>
</div>
<p><span style="font-family: 宋体">&nbsp;TEXTEQU可在程序中重复定义。</span></p>
<p>&nbsp;</p>
<h2><span style="font-family: 宋体">3.6 实模式</span></h2>
<h3><span style="font-family: 宋体">3.6.1 基本修改</span></h3>
<p><span style="font-family: 宋体">&nbsp; 将本章32位程序转换为16位程序, 只需做以下修改:</span></p>
<p><span style="font-family: 宋体">&nbsp;&nbsp; * INCLUDE指令引用不同的库文件: INCLUDE Irvine16.inc</span></p>
<p><span style="font-family: 宋体">&nbsp;&nbsp; * 启动过程开始必须插入两条指令, 初始化DS寄存器: mov ax, @data&nbsp;&nbsp;&nbsp; mov ds, ax</span></p>
<p><span style="font-family: 宋体">&nbsp;&nbsp; * 使用make16.dat批处理文件</span></p>
<p><span style="font-family: 宋体">&nbsp;&nbsp; * 数据标号和代码标号的偏移为16位而非32位</span></p>
<div class="cnblogs_code">
<pre>TITLE <span style="color: rgba(0, 0, 255, 1)">Add</span> <span style="color: rgba(0, 0, 255, 1)">and</span><span style="color: rgba(0, 0, 0, 1)"> Substract         (AddSub.asm)
</span><span style="color: rgba(0, 128, 0, 1)">;</span><span style="color: rgba(0, 128, 0, 1)"> This programs adds and substracts 32-bit integers.</span>
INCLUDE Irvine16.<span style="color: rgba(0, 0, 255, 1)">inc</span><span style="color: rgba(0, 0, 0, 1)">

.data
val1 DWORD 10000H
val2 DWORD 40000H
val3 DWORD 20000H
finalVal DWORD ?

.code
main PROC
      </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> ax, @data
      </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> ds, ax
    </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> eax, val1
    </span><span style="color: rgba(0, 0, 255, 1)">add</span><span style="color: rgba(0, 0, 0, 1)"> eax, val2
    </span><span style="color: rgba(0, 0, 255, 1)">sub</span><span style="color: rgba(0, 0, 0, 1)"> eax, val3
    </span><span style="color: rgba(0, 0, 255, 1)">mov</span><span style="color: rgba(0, 0, 0, 1)"> finalVal, eax
    </span><span style="color: rgba(0, 0, 255, 1)">call</span><span style="color: rgba(0, 0, 0, 1)"> DumpRegs
   
    exit
main ENDP
END main</span></pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">&nbsp;</span></p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/chenxingyang/p/11228384.html
頁: [1]
查看完整版本: 第三章 汇编语言基础