4.2 例题详解
例4.1 写出下面数据段中每个符号或变量所对应的值。
解
讨论
伪指令EQU前面的符号一定对应一个确定的值,该符号不占用也不对应内存空间。而数据定义语句DB、DW等要分配内存空间,其前面的符号名一定要对应确切的内存偏移量。符号名SIZE后面是一个表达式,其值要根据表达式的计算来求出,TWO的值小于20H,则结果为真,表示为0FFH,再和10H进行“与”运算,结果为10H,加10H,最后的值为20H。若TWO的值大于20H,则结果为假,表示为0,再和10H相“与”,结果为0,加10H,最后结果为10H。
例4.2 若有如下定义的数据段:
DATA SEGMENT
BUFl DB'ABCDl',ODH,OAH,'$'
BUF2 DW5 DUP(?)
BUF3 DD 4 DUP(?)
BUF4 DQ 1234567890ABCDEFH
BUF5 DT 2 DUP(?)
BUF6 DB 3 DUP'ERRORMSG!','S'
DATA ENDS
如果DATA为1600H,要求写出BUFl~BUF6的段值,段内偏移量属性值,类型值TYPE、LENGH及SIZE。
解
由于BUFl~BUF6都在同一个DATA段内,所以它们的段属性返回值是相同的,即SEG BUFl~SEG BUF6都等于1600H。
段内偏移量属性值如下:
OFFSET BUFl=0000H, OFFSET BUF2=0008H
OFFSET BUF3=0012H, OFFSET BUF4=0022H
OFFSET BUF5=002AH, OFFSET BUF6=003EH
类型值如下:
TYPE BUFl=1, TYPE BUF2=2
TYPEBUF3=4, TYPEBUF4=8
TYPEBUF5=10, TYPEBUF6=l
LENGTHBUFl=l, LENGTHBUF2=5
LENGTHBUF3=4, LENGTHBUF4=l
LENGTHBUF5=2, LENGTHBUF6=3
SIZE BUFl=1, SIZE BUF2=10
SIZE BUF3=16, SIZE BUF4=8
SIZE BUF5=20, SIZE BUF6=3
讨论
本题要注意数据定义语句DB、DW、DD、DQ、DT等的区别,它们对应的变量对内存单元的分配是不一样的。它们对应的存储单元数(字节单元)分别为1、2、4、8和10个。LENGTH与SIZE是有区别的,当使用DUP时,LENGTH返回分配给该变量的单元数;否则返回值为1。而SIZE的值为TYPE×LENGTH。
例4.3 编一程序,实现多字节组合型BCD码相加。若实现相减,程序应如何修改?若实现多字节二进制数加(减)法又如何修改?
解
·要实现多字节组合BCD码减法,只需将程序中的“ADC AL,[BX]”改为“SBB AL,[BX]”,把DAA指令改为DAS指令即可。
·要实现多字节二进制加法,只需将程序中的DAA指令去掉即可。
·要实现多字节二进制减法,只需将程序中的“ADC AL,[BX]”改为“SBB AL,[BX]”,把DAA指令去掉即可。
讨论
因为是多字节加法,所以要考虑低位向高位的进位CF,加法指令要用ADC。程序中用了串(装入和填充)操作指令LODSB和STOSB,其地址SI和DI是自动修改的,在装入初值时要指向多字节BCD码的最低位。
例4.4 下面程序的功能是:在附加段的地址为BUF中有一50个无符号数的字数组,找出最大数和最小数,分别存放在AX和BX寄存器中。请填空完成该程序。
解
根据题意在相应位置填入以下语句:
①ASSUME CS:CODE,ES:EDATA
②MOV ES,AX
③MOV DI,OFFSET BUF
④JNC MAX
⑤MOV AX,ES:[DI]
讨论
在一个宏汇编源程序中,不能省略ASSUME语句,该语句指明了所定义的各段与CPU中段寄存器的对应关系。若省略该语句,则汇编程序就找不到所定义的各个段了。一个源程序中可以允许定义多个代码段和其他段,也允许多次使用ASSUME语句,重新定义段寄存器和段的关系。除了CS以外,各个段寄存器的实际值必须用MOV指令来赋值。所以“MOV ES,AX”用来给ES赋初值。
例4.5 编一程序把键入的十六进制数转换成十进制数。要求:
①在屏幕上显示转换的十进制数,键入的最大数为FFFFH;
②若键入非十六进制数,则显示出错提示;
③程序中至少用到一个子程序和一个宏指令,若键入CTRL+C则返回系统。
解
讨论
本题主程序很简单,而子程序有的较复杂。本题有两个主要的子程序,一个是子程序HEXBIN,它把键入的字符由十六进制转换为二进制。该程序首先判断键入的字符是否为合法的十六进制字符,若是十六进制字符,则将其存放在BX中,接着再接收下一个新的字符,同时将上一个字符左移4位,与刚键入的字符相加,仍存放在BX中,依次类推。若键入的是非法的字符,则显示错误信息,返回开始处重新输入;若键入回车符,则本次键入的字符结束,下面进入转换程序。另一个子程序为BINDEC,它把二进制数转换成十进制数。其方法是,把键入的若干位十六进制数除以10 000,将余数再分别除以1 000,100,10,1,把每次所得的商变为ASCII码在屏幕上显示出来,每次所得的商即要转换成的十进制数。因为假设键入的最大数是FFFFH(65535D),所以开始除以10 000即可。若不用除法,使用减法也可以,把键入的数分别减10 000,1 000,…,看BX中有几个万,几个千,几个百,…,其道理与除法是一样的。
例4.6 在内存地址以BUFF开始的单元中存放有100字节的符号数。编一程序求其平均值并将结果存于X单元,求出负数之和与正数之和,分别存于Y和Z单元。
解
讨论
本题先从内存中取出数据,判断该数据是正数还是负数,若是正数就和正数相加(以字为单位,可以不考虑进位),负数与负数相加,于是正数之和与负数之和就可求出。然后用除法求其平均值。本题也可以采用以字节为单位的方法进行加法运算,但要考虑每次相加后的进位,因为多字节加法一定要保存每次向高位的进位。
例4.7 编一程序,统计一个以′$′结尾的字符串的长度,并要求滤去第一个非空格字符之前的所有空格。
解
讨论
在编程时,若循环次数已知,通常将循环次数送入CX,然后用LOOP指令就可以控制循环。但若循环次数未知,循环次数将根据给定的某种条件来判定。本题的循环次数是未知的,给定的条件有两个,第一是要找到第一个非空格字符,第二是从第一个非空格字符开始统计字符串的长度。所以程序包括两个循环,第一个循环的结束条件是找到非空格字符,第二个循环的结束条件是找到字符′$′。
例4.8 已知多位数x(如8字节)的补码,编一程序求-x的补码。
解
根据补码的定义,可采用0减去该多位数实现。