SCAU 汇编实验三 将寄存器中的无符号数和有符号数以二进制、八进制、十六进制、十进制的形式输出
1.将BX中的无符号数以二进制的形式输出
;将bx中的无符号数以二进制的形式输出
;关键:利用CF程序状态字配合ADC指令来判断ROL循环左移出的字符是0还是1
DATAS SEGMENT
A DW 6C3BH
DATAS ENDS
STACKS SEGMENT
DB 100 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV CX,10H ;循环16次
MOV BX,A
L1:
ROL BX,1 ;温馨提醒,移位指令的后面那个操作数只能是CL或者1,切记
MOV DL,30H ;将数值转化ASCII码
ADC DL,0 ;利用CF程序状态字来判断左移出的字符是0还是1
MOV AH,2
INT 21H
LOOP L1
MOV AH,4CH
INT 21H
CODES ENDS
END START
2.将BX中的无符号数以八进制的形式输出
;将bx中的无符号数以八进制的形式输出
;关键:16位二进制化成八进制,需要在16位二进制前面补两个零变成18位才能划分成刚好的6位八进制
;同时我们发现,如果不补零,6位八进制的最高位由于缺了高两位,所以转换后八进制的最高位只能是零或一
;所以一开始先单独将最高位移出,单独判断即可,余下的二进制数每三位循环左移来判断数值
DATAS SEGMENT
A DW 6C3BH
DATAS ENDS
STACKS SEGMENT
DB 100 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV CH,5 ;十六位二进制化成八进制最多有16/3+1=6位,除开一开始单独处理的最高位,余下位循环5次即可
MOV CL,3 ;CX寄存器不太够用,拆开两块来用,CL控制循环左移次数
;待会转16进制时再演示利用栈来重复使用cx的方法
ROL A,1 ;先判断最高位
MOV DX,A
MOV DL,30H
ADC DL,0 ;利用CF程序状态字来判断左移出的字符是0还是1
MOV AH,2
INT 21H
L3:
ROL A,CL ;将最高的三位循环左移,挪到最右边
MOV BX,A
AND BX,0007H;屏蔽前13位,只保留最后3位(AND 0000 0000 0000 0111)
MOV DL,30H
ADD DL,BL ;BX不会太大,所以用BL无所谓了,转到dl然后输出
MOV AH,2
INT 21H
DEC CH
CMP CH,0
JNZ L3
MOV AH,4CH
INT 21H
CODES ENDS
END START
3.将BX中的无符号数以十六进制的形式输出
;将bx中的无符号数以十六进制的形式输出
;关键:①利用循环左移将最高的四位二进制数字输出(左移先输出最高位,可以省去栈)
; ②0-9和a-f的acsll码是有偏差的,所以需要分别判断所求的数字是在哪个区间,才能输出相应的字符)
; 0是30H,A是41H
DATAS SEGMENT
A DW 6C3BH
DATAS ENDS
STACKS SEGMENT
DB 100 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV CX,4 ;十六进制最多有16/4=4位,循环4次即可
L1: PUSH CX ;将循环次数的控制数入栈,待会loop前再pop出来即可,下面就能正常使用cl了
MOV CL,4
ROL A,CL ;将最高的四位循环左移,挪到最右边
MOV BX,A
AND BX,0FH;屏蔽前12位,只保留最后4位
CMP BX,9 ;判断数字是在哪个区间
JA L2 ;如果bx大于9,去L2玩
MOV DL,30H
ADD DL,BL ;输出
MOV AH,2
INT 21H
POP CX
LOOP L1
L2:
MOV DL,37H ;41H-A=37H
ADD DL,BL ;输出
MOV AH,2
INT 21H
POP CX
LOOP L1
MOV AH,4CH
INT 21H
CODES ENDS
END START
4.将BX中的无符号数以十进制的形式输出
;将bx中的无符号数以十进制的形式输出
;关键:正如我们在求某个数的二进制表示时,曾经会用到不断除以2取余数的方法
; 在汇编中求十进制表示也是同样的思路,将二进制数不断除以十取余数,商为零就停止
DATAS SEGMENT
A DW 6C3BH
COUNT DW 0
DATAS ENDS
STACKS SEGMENT
DB 100 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV AX,A
MOV CX,10 ;待会一直除以10取余数,值得提醒的是,一个十六位二进制数除以10,
;是不一定能放得进八位寄存器的,所以这里要使用cx来装载除数
;使得待会机器自动以(DX,AX)/SRC->AX(商),DX(余数)的方式来运算
;如果使用cl等寄存器,会提示divide error(除0错误)
L1: XOR DX,DX ;务必记得,余数是有用到dx的,每次除法都务必先清空
DIV CX ;除以10
PUSH DX ;余数入栈
INC COUNT
CMP AX,0 ;商为0就走
JNE L1
L2:
POP DX
ADD DX,30H
DEC COUNT
CMP COUNT,0
MOV AH,2 ;栈中数字pop输出即为最终答案
INT 21H
JNE L2
MOV AH,4CH
INT 21H
CODES ENDS
END START
5.将BX中的有符号数以十进制的形式输出
;将bx中的有符号数以十进制的形式输出,即输出范围为-32768到32767,思路很简单
;0-32767的输出方式沿用上面输出无符号数的代码,-32768到-1的代码输出时加个负号再减就okk
;而负数段='-'+(65536-被操作数)
;而汇编中提供了NEG指令来处理【65536-被操作数】这个操作,所以处理负数之前只要将被操作数neg一下就好了
DATAS SEGMENT
A DW 65535
COUNT DW 0
DATAS ENDS
STACKS SEGMENT
DB 100 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV AX,A
MOV CX,10
CMP AX,0 ; CMP AX,32767 这里要判断数是正数还是负数
JL L2 ; JA L2 其实用有符号数比较转移指令,cmp数和0就行,小于0就是负数
L1: XOR DX,DX ;判断为正数就循环执行L1,最后L5输出
IDIV CX
PUSH DX
INC COUNT
CMP AX,0
JNE L1
JMP L5
L2: NEG AX ;判断为负数,则先求补,再进行和正数一毛一样的求十进制做法
L3: XOR DX,DX
IDIV CX
PUSH DX
INC COUNT
CMP AX,0
JNE L3
JMP L4
L4: MOV DL,'-' ;如果判断为负数,输出数字前先输出一个负号
MOV AH,2
INT 21H
L5: ;从栈中倒序输出
POP DX
ADD DX,30H
DEC COUNT
CMP COUNT,0
MOV AH,2
INT 21H
JNE L5
MOV AH,4CH
INT 21H
CODES ENDS
END START
6.教材习题(代码段)P193
5.1 输入小写字母显示相应的大写字母
L1:
MOV AH,7
INT 21H
CMP AL,'a' ;输入合法性检查
JB L1
CMP AL,'z'
JA L1
MOV DL,AL
SUB DL,20H
MOV AH,2
INT 21H
5.2 输入小写字母 顺序输出周围两个字符和它本身
L1:
MOV AH,7
INT 21H
MOV DL,AL
CMP AL,'a'
JB L1
CMP AL,'z'
JA L1
MOV CX,3
DEC DL
L2: MOV AH,2
INT 21H
INC DL
LOOP L2
5.3 将AX拆成四份,分别存放在AL,BL,CL,DL中
MOV AX,0ABCDH
MOV DX,AX ;存个备份
AND AX,0F000H
MOV CL,4
ROL AX,CL
MOV BX,DX
AND BX,0F00H
MOV CL,8
SHR BX,CL
MOV CX,DX
AND CX,0F0H
SHR CX,1 ;移位指令的CNT在8086里只能是1和CL,但是CL最后要存东西,那就简单粗暴一点
SHR CX,1
SHR CX,1
SHR CX,1
AND DX,0FH
AX原内容:0ABCDH
结果: