汇编语言基础
本章侧重于 Microsoft MASM 汇编程序的基本组成部分,通过学习将会了解到如何定义常数和变量,数字和字符常量的标准格式,以及怎样汇编并运行你的第一个程序。
第一个汇编语言程序
汇编语言以隐晦难懂而著名,但是它也是一种几乎提供了全部信息的语言。程序员可以看到正在发生的事情,甚至包括 CPU 中的寄存器和标志。
但是,在拥有这种能力的同时,程序员必须负责处理数据表示的细节和指令的格式。程序员工作在一个具有大量详细信息的层次。现在以一个简单的汇编语言程序为例,来了解其工作过程。
程序执行两个数相加,并将结果保存在寄存器中。程序名称为 AddTwo
:
1: main PROC 2: move eax, 5 ; 将数字 5 送入 eax 寄存器 3: add eax, 6 ; eax 寄存器加 6 4: 5: INVOKE ExitProcess, 0 ; 程序结束 6: main ENDP
现在按照一次一行代码的方法来仔细查看这段程序:
- 第 1 行开始 main 程序(主程序),即程序的入口;
- 第 2 行将数字 5 送入 eax 寄存器;
- 第 3 行把 6 加到 EAX 的值上,得到新值 11 ;
- 第 5 行调用 Windows 服务(也被称为函数)
ExitProcess
停止程序,并将控制权还给操作系统; - 第 6 行是主程序结束的标记。
大家可能已经注意到了程序中包含的注释,它总是用分号开头。
它不会将全部信息显示在屏幕上,但是借助工具程序调试器的运行,程序员可以按一次一行代码的方式执行程序,并查看寄存器的值。
#. 添加一个变量
现在让程序变得有趣些,将加法运算的结果保存在变量 sum
中,要实现这一点,需要增加一些标记,或声明,用来标识程序的代码和数据区:
1: .data ; 此为数据区 2: sum DWORD 0 ; 定义名为 sum 的变量 3: 4: .code ; 此为代码区 5: main PROC 6: mov eax,5 ; 将数字 5 送入 eax 寄存器 7: add eax,6 ; eax 寄存器加 6 8: mox sum,eax 9: 10: INVOKE ExitProcess,0 ; 结束程序 11: main ENDP
变量 sum
在第 2 行进行了声明,其大小为 32 位,使用了关键字 DWORD
。汇编语言中有很多这样的大小关键字,其作用或多或少与数据类型一样。
但是与程序员可能熟悉的类型相比它们没有它们那么具体,比如 int、double、float
等等。这些关键字只限制大小,并不检查变量中存放的内容。记住,程序员拥有完全控制权。
*注:那些被 .code
和 .data
伪指令标记的代码和数据区,被称为段,即程序有代码段和数据段。
汇编语言常量
常量 (constant)是程序中使用的一个确定数值,在汇编阶段就可以确定,直接编码于指令代码中,不是保存在存储器中可变的变量,因为是编码在指令中的量,和指令一起存储了,所以不用单独开辟主存空间,所以也就没法动态改变它了,这也正是高级语言常量无法修改的原因。
整数常量
整数常量(integer literal),又称为整型常量(integer constant),由一个可选前置符号、一个或多个数字,以及一个指明其基数的可选基数字符构成:
[{+|-}] digits [radix]
下表中列出了可能的基数值:
h | 十六进制 | 1Ah, 0A3h |
r | 编码实数 |
q/o | 八进制 | 42o |
||
d | 十进制 | 26, 26d |
t | 十进制(备用) |
b | 二进制 | 11010011b |
y | 二进制(备用) |
*注:以字母开头的十六进制数必须加个前置 0
,以防汇编器将其解释为标识符。
整型常量表达式
整型常量表达式(constant integer expression)是一种算术表达式,它包含了整数常量和算术运算符。每个结果必须是一个整数,并可用 32 位(从 0
到 FFFFFFh
)来存放。
下表列出了算术运算符,并按照从高(1)到低(4)的顺序给出了它们的优先级,对整型表达式而言很重要的是,要意识到它们只在汇编时计算,这里将它们简称为整数表达式:
运算符 | 名称 | 优先级 |
---|---|---|
() |
圆括号 | 1 |
+, - |
一元加、减 | 2 |
*, / |
乘、除 | 3 |
MOD |
取模 | 3 |
+, - |
加、减 | 4 |
*注:其实,在表达式中使用圆括号来表明操作顺序,那么就不用去死记运算符优先级。