学习C语言时,首先要了解数据类型,以掌握如何用常量和变量表达数据。C语言的基本数据类型有字符char、整型int(包括短整型short和长整型long),以及浮点单精度float和双精度double。本章讨论最基本的整数编码,包括整型和字符,因为字符本质上是ASCII码值,属于8位整数。两种浮点数据类型将在第9章介绍。
那么,汇编语言又怎样使用常量和变量形式表达整数编码呢?基于前面的基本知识,本节先介绍如何使用常量表示数值和字符,下一节说明怎样将它们保存在存储器中,最后一节讲解处理器指令如何访问它们。
常量(Constant)是程序中使用的一个确定数值,在汇编语言中有多种表达形式。
常数是指由十进制、十六进制和二进制形式表达的数值,如表2-5所示。各种进制的数据以后缀字母区分,默认不加后缀字母的是十进制数。十六进制常数若以字母A~F开头,则要添加前导0来避免与以这些字母开头的标识符混淆。例如,十进制数10用十六进制表达为A,汇编语言需要表达成0AH,如果不用前导0,则将与寄存器名AH相混淆。在C和C++语言中,十六进制数使用0x前导,因此不会出现这个问题。
表2-5 各种进制的常数
程序设计语言通常都支持八进制数,但现在已经较少使用,本书不再介绍。
字符或字符串常量是用英文单引号或双引号括起来的单个字符或多个字符,其数值是每个字符对应的ASCII码值。例如,'d'(=64H)、'AB'、'Hello,Assembly!'。在支持汉字的系统中,也可以括起汉字,每个汉字是两个字节,为汉字机内码或Unicode。
如果字符串中有单引号本身,则可以用双引号括起来,反之亦然。例如:
也可以直接用单引号或者双引号的ASCII值(单引号的ASCII值为27H,双引号的ASCII值为22H)。
符号常量使用标识符表达一个数值。常量若使用有意义的符号名来表示,可以提高程序的可读性,同时更具有通用性。程序中可以多次使用符号常量,但修改时只需改变一处。例如,高级语言中把常用的数值定义为符号常量并保存为常量定义文件,通过包含该文件,程序中就可以直接使用它们。MASM汇编语言中也可以如此应用。
MASM提供的符号定义伪指令主要有“EQU”,用来为常量定义符号名,格式为:
等价伪指令EQU给符号名定义一个数值或定义成另一个字符串,这个字符串甚至可以是一条处理器指令。例如:
MASM还提供“=”等号伪指令,也可以用于定义常量,格式为:
EQU用于数值等价时不能重复定义符号名,但“=”允许有重复赋值。例如:
数值表达式是指用运算符(MASM中统称为操作符,Operator)连接各种常量所构成的算式。汇编程序在汇编过程中计算表达式,最终得到一个确定的数值,所以也属于常量。由于表达式是在程序运行前的汇编阶段计算的,所以必须在汇编时就确定组成表达式的各部分。汇编语言支持多种运算符,但主要应用算术运算符:+(加)、-(减)、*(乘)、/(除)和MOD(取余数)。当然,还可以运用圆括号表达运算的先后顺序。
MOD用于进行除法取余数,例如,“10 MOD 4”的结果是“2”。
对于整数数值表达式或地址表达式,参加运算的数值和运算结果必须是整数,除法运算的结果只有商,没有余数。地址表达式只能使用加减,常用“地址+常量”或“地址-常量”的形式指示地址移动常量表示的若干个存储单元,注意存储单元的单位是字节。
[例2-1]数据表达程序
本示例程序用于说明各种数据的表达形式,用到了定义字节变量DB伪指令。左边是列表文件内容,右边才是源程序本身(编辑源程序文件时,不要把左边的列表文件内容录入)。
数据段的第一行用不同进制和形式表达了同一个数值:100(=64H)。从这一行左边列表文件的5个“64”可以体会到:无论在源程序中如何表达,在计算机内部都是二进制编码。
随后两行给出一些典型数据,用于对比,例如,真值255和-1的机器代码(8位、字节量)都是FFH,128和-128都变换为80H,原因在于它们采用不同的编码,前者是无符号数,后者是补码表达的有符号数。从第3行看出105的补码是69H,-105的补码是97H(读者可以思考-32、-32H的补码分别是什么)。
第4行定义字符串,左边列表文件内容是每个字符的ASCII码值。
随后定义两个数值0DH和0AH,它们分别是ASCII码表中的回车符和换行符,注意前导0不能省略(否则成为DH和AH,与两个8位寄存器重名),数字0表示字符串结尾,调用显示功能时需要它。
符号常量MININT的数值为10,MAXINT的数值为255,它们只是一个符号,并不占主存空间,应用时可直接用其代表的内容替代。
接着,CONST6用表达式定义,但实质还是一个常量,例如,表达式“4*4”计算后为16,对应列表内容是10(表示十六进制10H,即十进制16)。
代码段从CONST4开始显示,遇到0结束,所以程序运行后的显示结果是:0123456789 abcxyz-ABCXYZ。
第1章介绍了汇编语言的开发过程。对于以后各章的程序,读者亲自上机实践,逐渐就能熟练掌握MASM汇编语言程序的开发方法。汇编过程中,建议生成列表文件;连接生成可执行文件之后,要运行并查看结果,以获得直观的感受。配合查阅列表文件、观察运行结果,教材中的许多解释往往就比较容易理解和掌握了。相信有过高级语言编程经历的读者都有深刻的体会:通过源程序的编辑、编译(汇编)、连接,以及可执行文件的运行、错误的排除和调试等一系列上机实践过程,对很多问题常有恍然大悟的感觉,看似艰涩难懂或长篇大论的说明也一目了然了。
NASM汇编程序表达常量与MASM类似(详见附录G),但有如下简单区别。
● NASM中,各种进制的常数还可以采用前缀字母区别,例如像高级语言一样使用“0x”表示十六进制数。
● NASM不支持“=”伪指令。
例2-1的程序同样可使用NASM进行汇编。读者不妨实践一下,还可以改用C语言函数printf实现最后的字符串显示。