题目:键盘输入任意一个字母,显示其前导字母、字母自身、后续字符共三个字母。
逐句详解
如有前置知识障碍,请移步本专栏前两篇文章:汇编语言(Assembly Language)常用的系统功能调用
汇编语言(Assembly Language)习题:键盘输入一个字符串,试将其中的小写字母转换为大写字母,其它字符保持不变。
DATAS SEGMENT
DATAS SEGMENT
;此处输入数据段代码
MSG1 DB 'Please input a letter :$'
MSG2 DB 0dh,0ah,'The previous letter is :$'
MSG3 DB 0dh,0ah,'The next letter is :$'
DATAS ENDS
这里主要是要输入的语句,使用9号调用输出。
CODES SEGMENT(1)
MOV DX,OFFSET MSG1 ;显示提示信息1
MOV AH,09H
INT 21H
MOV AH,01H ;等待用户输入
INT 21H ;从键盘输入字符的ASCII码送入寄存器AL中,并送显示器显示。
MOV BX,AX ;将AX的值赋值给BX,相当于复制了一份AX的数据,至于为什么请看后文
CMP AL,'A'
JZ changeA ;如果AL的值与'A'相等,就跳转到changeA ,类似C语言中的goto语句
CMP AL,'a'
JZ changea1
CMP BL,'Z' ;这里也可以直接写成CMP AL,'Z' ,主要是为了方便辨识
JZ changeZ
CMP BL,'z'
JZ changez1
DEC AL ;-1计算前导字符
INC BL ;+1计算后继字符
JMP PUSH1
本题看似简单,却有一点易错,对于非 ‘a’,‘A’,‘z’,‘Z’ 字符只需要输出其前一个ASCII码和后一个ASCII码即可,而 ‘a’,‘A’,‘z’,‘Z’ 则应该输出’a’,‘A’前置 ‘z’,‘Z’ ,‘z’,‘Z’ 后置’a’,‘A’ ,应该有另外的程序,这里需要使用跳转指令:
这组指令单独判断5个状态标志之一:
(1) JZ/JE和JNZ/JNE
利用零标志ZF,判断结果是否为零(或相等)
(2)JS和JNS
利用符号标志SF,判断结果是正是负
(3)JO和JNO
利用溢出标志OF,判断结果是否产生溢出
(4)JP/JPE和JNP/JPO
利用奇偶标志PF,判断结果中“1”的个数是偶是奇
(5)JC/JB/JNAE和JNC/JNB/JAE
利用进位标志CF,判断结果是否进位或借位
CODES SEGMENT(2)
changeA: ADD AL,25
INC BL
JMP PUSH1
changea1: ADD AL,25
INC BL
JMP PUSH1
changeZ: SUB BL,25
DEC AL
JMP PUSH1
changez1: SUB BL,25
DEC AL
JMP PUSH1
PUSH1:PUSH BX ;保存BX内容即后继字符
PUSH AX ;保存AX内容即前导字符
MOV DX,OFFSET MSG2 ;显示提示信息2
MOV AH,09H
INT 21H
POP AX ;AX内容即前导字符出栈
MOV DL,AL ;AL内容送入DL(存放的是ASCLL码),准备输出
MOV AH,02H ;输出前导字符
INT 21H
MOV DX,OFFSET MSG3 ;显示提示信息3
MOV AH,09H
INT 21H
POP BX ;BX内容即后继字符出栈
MOV DL,BL ;BL内容送入DL(存放的是ASCLL码),准备输出
MOV AH,02H ;输出后继字符
INT 21H
对于’a’,‘A’,‘z’,‘Z’ 对输出的AL,BL值特殊处理,最后殊途同归到PUSH1:将BX,AX内容压栈,需要时再取出。这样可以避免寄存器放不下那么多数据,堆栈是先进后出方式工作,如果用好会对程序优化起到很大帮助。
对于16位指令:
进栈指令: PUSH SRC
执行操作: (SP) <-(SP) – 2
( (SP)+1, (SP) ) <- (SRC)
出栈指令: POP DST
执行操作: (DST) <- ( (SP)+1, (SP) )
(SP) <- (SP) + 2
堆栈:‘先进后出’的存储区,存在于堆栈段中,SP 在
任何时候都指向栈顶。
注意:
* 堆栈操作必须以字为单位。
* 不影响标志位*
* 不能用立即寻址方式 PUSH 1234H (error)
* DST不能是CS POP CS (error)
完整代码:
DATAS SEGMENT
;此处输入数据段代码
MSG1 DB 'Please input a letter :$'
MSG2 DB 0dh,0ah,'The previous letter is :$'
MSG3 DB 0dh,0ah,'The next letter is :$'
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
;此处输入代码段代码
MOV DX,OFFSET MSG1 ;显示提示信息1
MOV AH,09H
INT 21H
MOV AH,01H ;等待用户输入
INT 21H
MOV BX,AX
CMP AL,'A'
JZ changeA
CMP AL,'a'
JZ changea1
CMP BL,'Z'
JZ changeZ
CMP BL,'z'
JZ changez1
DEC AL ;-1计算前导字符
INC BL ;+1计算后继字符
JMP PUSH1
changeA: ADD AL,25
INC BL
JMP PUSH1
changea1: ADD AL,25
INC BL
JMP PUSH1
changeZ: SUB BL,25
DEC AL
JMP PUSH1
changez1: SUB BL,25
DEC AL
JMP PUSH1
PUSH1:PUSH BX ;保存BX内容即后继字符
PUSH AX ;保存AX内容即前导字符
MOV DX,OFFSET MSG2;显示提示信息2
MOV AH,09H
INT 21H
POP AX ;AX内容即前导字符出栈
MOV DL,AL ;AL内容送入DL(存放的是ASCLL码),准备输出
MOV AH,02H ;输出前导字符
INT 21H
MOV DX,OFFSET MSG3 ;显示提示信息3
MOV AH,09H
INT 21H
POP BX ;BX内容即后继字符出栈
MOV DL,BL ;BL内容送入DL(存放的是ASCLL码),准备输出
MOV AH,02H ;输出后继字符
INT 21H
MOV AH,4CH
INT 21H
CODES ENDS
END START