EXTRN LOAD:FAR,SAVE:FAR
N EQU 20
DSEG SEGMENT
SOURCE DB N DUP(?)
RESULT DB N/2 DUP(0)
NAME0 DB 'INPUT1.DAT',0
NAME1 DB 'OUTPUT1.DAT',0
DSEG ENDS
SSEG SEGMENT STACK
DB 256 DUP(?)
SSEG ENDS
CSEG SEGMENT
ASSUME CS:CSEG, SS:SSEG, DS:DSEG
START PROC FAR
PUSH DS
XOR AX,AX
PUSH AX
MOV AX,DSEG
MOV DS,AX
MOV ES,AX
LEA DX,SOURCE
LEA SI,NAME0
MOV CX,N
CALL LOAD
; **** BEGIN ****
MOV CX,0
LEA BX,SOURCE
NEXT: MOV AL,[BX]
CMP AL,0
JZ GOON
INC CX
INC BX
JMP NEXT
GOON: LEA SI,SOURCE
LEA DI,RESULT
ROR CX,1 ;是偶数吗?
JNC EVN ;是
ROL CX,1 ;否
LODSB
AND ____(1)__AL__,0FH
STOSB
DEC CX
ROR CX,1
EVN: LODSB
AND ____(2)_AL___,0FH
MOV BL,AL
LODSB
PUSH CX
MOV CL,___4_(3)____
SAL AL,___CL_(4)____
POP CX
____(5)_OR___ AL,BL
STOSB
LOOP EVN
; **** END ****
EXIT: LEA DX,RESULT
LEA SI,NAME1
MOV CX,N/2
CALL SAVE
RET
START ENDP
CSEG ENDS
END STA
★此程序要首先理解什么是压缩的BCD码。压缩的BCD码就是一字节存放两位BCD码。还要懂得如何将十进制的ASCII码转换成BCD码。考查了ROR,ROL,LODSB,STOSB等指令的用法。
程序的数据段中定义了四个字节型变量,原始数据区SOURCE、结果数据区RESULT、原始数据文件名NAME0、结果数据文件名NAME1。数据段下面是堆栈段,定义了一个256个字节的堆栈区。堆栈段下面是代码段,告诉汇编程序,代码段、数据段和堆栈段分别属于段寄存器CS、DS、SS。
先来看NEXT这一段程序,将BX中的内容送AL中。BX是原始数据的偏移地址,其初值为0。将AL与末尾字符0比较,若相等,则转向GOON段;否则,CX和BX都加1,继续转向NEXT段。所以NEXT段的作用是统计ASCII码字符的个数,用CX来表示。
GOON段,先将原始数据的偏移地址送SI中,结果数据存放的偏移地址送DI中。开始判断ASCII码字符的个数即CX为奇数还是偶数。将CX循环逻辑右移一位,将最低位移入CF中。由CF来判断CX的奇偶性。若CF=0,表示CX为偶数,则转向ECN段;否则,CX为奇数时,将CX循环逻辑左移一位,CX恢复原值。再用LODSB指令将由SI作为地址指针的串元素装入到AL中,同时修改SI,指向下一个元素。
第(1)空中,当CX为奇数时,要将地址最低的ASCII码即第一个ASCII码按照非组合BCD码格式转换,即一个字节只存第一个的BCD码。所以只需将AL的高四位屏蔽掉,再用STOSB指令将AL存储到DI中。
EVN段,当ASCII码字符个数CX为偶数时,接连取两个数,将前一个数AL(如34H)的高四位屏蔽掉,并赋值给BL(04H);再用LODSB指令取下一个数AL(如35H),将AL算术左移四位,原来的低四位移入到高四位,低四位变成0(得到50H)。所以第(2)、(3)、(4)分别填写“AL”,“4”,“CL”。
第(5)空是将转换后的两个BCD码相或操作,就变成了压缩BCD码(54H)。所以第(5)空填写“OR”。
数字+0x30就是对应的ASCII码了。。。。比如'0'=0+030H