SCAU 汇编实验三

实验前置知识

  1. 无论是字符还是数字,在计算机中都是以位向量(即0\1串)储存的。每个位向量唯一代表一个字符或数字。因此,字符‘0’和数字0的位向量是不同的,‘0’的ASCII码是30H(或者说是48),该ASCII码对应一个8位的位向量(具体多少不用关心);而数字0的位向量是0000 0000(其实数字的位向量可以通过把数字转化为2进制数字来得到)。所以请记住,寄存器中n位的位向量其实代表一个具体的(十进制)数字
  2. 数字和字符之间相互转化的关系
    数字0~9 加上30H ——>‘0’~‘9’
    数字A~Z 加上37H ——>‘A’~‘Z’

1、将BX中的无符号数以二进制形式输出

算法分析:
在这里插入图片描述

代码:

DATAS SEGMENT
    ;此处输入数据段代码  
DATAS ENDS

STACKS SEGMENT
       DB 30H DUP(0)
   TOP LABEL WORD
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    MOV AX,STACKS
    MOV SS,AX
    MOV SP,TOP;此题用不到数据段和堆栈段,也可以不用初始化
    
    XOR BX,BX
    MOV BL,7;BX随便什么数字都行
	MOV CL,16
	;算法核心部分;
L1:	MOV DL,30H ;输入输出都是以字符形式来实现的,
				;所以必须把数字转化为形式相同的字符,
				;这样才能把数字显示在屏幕上
    SHL BX,1
    ADC DL,0
    ;算法核心部分
    
    MOV AH,2 ;前面的DL存好数据了
    INT 21H
    LOOP L1
    
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

2、将BX中的无符号数以八进制形式输出

算法分析:
在这里插入图片描述

代码:

DATAS SEGMENT
    ;此处输入数据段代码  
DATAS ENDS

STACKS SEGMENT
       DB 30H DUP(0)
   TOP LABEL WORD
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    MOV AX,STACKS
    MOV SS,AX
    MOV SP,TOP
    
    XOR BX,BX
    MOV BX,70  ;BX随便什么数字都行
    
    ;先把最高位处理了,剩下的刚好是3位一组,共5组
    MOV DL,30H ;重置DL顺带方便待会数字转换成数字字符
    SHL BX,1
    ADC DL,0
    MOV AH,2
    INT 21H
    
	MOV CX,5;剩下的数字可分为5组(5次循环)
L1: PUSH CX  ;因为下面的指令需要用到CX,这里进栈保存一下循环的次数
	;算法核心部分;
	MOV CL,3
	ROL BX,CL
	MOV DX,BX ;保留BX内数据
	AND DL,7  ;获取BX最后三位位向量(注意:这三位位向量
			  ;其实就代表一个真实的数字,不管我们把它
			  ;写成十进制还是八进制)
	ADD DL,30H  ;数字转化成与之形式相同的字符
    ;算法核心部分    
    MOV AH,2
    INT 21H
    POP CX  ;恢复之前保护的循环次数
    LOOP L1
    
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

Tips:最后屏幕上显示的就是八进制数字

3、将BX中的无符号数以十六进制形式输出

算法分析:
在这里插入图片描述

代码:

DATAS SEGMENT
    ;此处输入数据段代码  
DATAS ENDS

STACKS SEGMENT
       DB 30H DUP(0)
   TOP LABEL WORD
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    MOV AX,STACKS
    MOV SS,AX
    MOV SP,TOP
    
    XOR BX,BX
    MOV BX,6C3BH ;BX随便什么数字都行
    
	MOV CX,4;剩下的数字可分为4组(4次循环)
L1: PUSH CX  ;因为下面的指令需要用到CX,这里进栈保存一下循环的次数
	;算法核心部分;
	MOV CL,4
	ROL BX,CL
	MOV DX,BX ;保留BX内数据
	AND DL,15  ;获取BX最后四位位向量
			   ;(但是!!!单个十六进制数字
			   ;有数字形式还有字母形式,所以需要判别,
			   ;是转化为数字字符还是字母字符)
	CMP DL,0AH;判断是否大于等于10
	JGE L2
	ADD DL,30H;小于10说明应转化为数字字符
	JMP L3
	
L2: ADD DL,37H;大于等于10说明应转化为字母字符
    ;算法核心部分    
L3: MOV AH,2
    INT 21H
    POP CX  ;恢复循环次数
    LOOP L1
    
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

4、将BX中的无符号数以十进制形式输出

算法分析:
文章开头前置知识里提过,位向量就代表一个数字。相信大家C语言都做过一道拆分整数的每个数字显示每个数字的算法题。这第4小题其实就是拆分数字再显示出来。**算法步骤见下图。**被除数的位向量除以10,得到的就是商和余数的位向量,分别存在寄存器中,这时把数字转换为字符就可以用DOS功能调用把数字字符显示出来。
在这里插入图片描述

代码:

DATAS SEGMENT
COUNT DB 0 ;压入栈内的数字总数
DATAS ENDS

STACKS SEGMENT
       DB 30H DUP(0)
   TOP LABEL WORD
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    MOV AX,STACKS
    MOV SS,AX
    MOV SP,TOP
    
    XOR BX,BX
    MOV BX,6C3BH ;BX随便什么数字都行(6C3BH = 27707)
    
    MOV AX,BX 
	;算法核心部分;
L1: XOR DX,DX  ;重置准备工作
	MOV SI,10
	DIV SI    ;除法指令不接受立即数!!
	PUSH DX
	INC COUNT
	CMP AX,0  ;商为0则数字拆分结束
	JNE L1
	
    ;算法核心部分
    XOR CX,CX
    MOV CL,COUNT ;栈内有几个数字,就应循环弹出几次
L2: POP DX
	ADD DL,30H ;转化成字符      
    MOV AH,2
    INT 21H
    LOOP L2
    
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

5、将BX中的有符号数以十进制形式输出

**算法分析:**简直跟第四小题一模一样,只需要判断一下是正数还是负数,正数直接按无符号数处理;负数进行求补运算,变成负数的相反数(正数),这时就可以按照无符号数处理。
代码:

DATAS SEGMENT
COUNT DB 0 ;压入栈内的数字总数
DATAS ENDS

STACKS SEGMENT
       DB 30H DUP(0)
   TOP LABEL WORD
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    MOV AX,STACKS
    MOV SS,AX
    MOV SP,TOP
    
    MOV BX,0FFFFH ;特地放入一个16位全为1的位向量(有符号形式代表-1)
    
    ;判断符号位是否为1;  1、JL指令 2、TEST BX,8000H,JC
    CMP BX,0 
    JL  L1 ;是负数
    JMP L2 ;不是负数,跳过负数的处理部分
    
	;算法核心部分;
L1:	NEG BX   ;把负数求补,变成其相反数(想想负数的补码与其相反数的补码的转换关系)
	MOV DL,'-' ;先把符号显示出来
	MOV AH,2
	INT 21H
	
	;拆分整数获得各位上的数字
	MOV AX,BX
L2: XOR DX,DX
	MOV SI,10
	DIV SI
	PUSH DX
	INC COUNT
	CMP AX,0
	JNE L2 ;商不为0继续拆分数字
    ;算法核心部分;
    XOR CX,CX
    MOV CL,COUNT ;栈内有几个数字,就应循环弹出几次
L3: POP DX
	ADD DL,30H ;转化成字符      
    MOV AH,2
    INT 21H
    LOOP L3
    
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

6、第五章习题5.1-5.3

5.1 把键盘输入的小写字母转换成大写字母并显示出来

代码:

DATAS SEGMENT
      ;输入数据段代码
DATAS ENDS

STACKS SEGMENT
       DB 30H DUP(0)
   TOP LABEL WORD
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    MOV AX,STACKS
    MOV SS,AX
    MOV SP,TOP
    
L1: MOV AH,7
    INT 21H
    
    ;合法范围:'a'<=输入的字符<='z'
    CMP AL,0DH
    JE  L2     ;回车结束输入
    CMP AL,'a'
    JB  L1
    CMP AL,'z'
    JA  L1
    
    ;转换大写并显示
    MOV DL,AL
    SUB DL,20H ;小写转大写
    MOV AH,2
    INT 21H
    JMP L1
    
L2: MOV AH,4CH
    INT 21H
CODES ENDS
    END START

5.2 输入一个小写字母,找出它的前导字符和后续字符,按顺序显示这三个字符

代码:

DATAS SEGMENT
      ;输入数据段代码
DATAS ENDS

STACKS SEGMENT
       DB 30H DUP(0)
   TOP LABEL WORD
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    MOV AX,STACKS
    MOV SS,AX
    MOV SP,TOP
    
L1: XOR AX,AX
    MOV AH,1
	INT 21H
	
	;可省略的代码(美化输入的文字排版,相当于\n)
	PUSH AX  ;DOS2号功能会改变AL的值(书上没写)!需要进栈保存
    MOV AH,2   
	MOV DL,0DH
	INT 21H	
	MOV AH,2
	MOV DL,0AH
	INT 21H	
	POP AX    ;恢复原来AL的值
	;可省略的代码
	
	;检测是否合法
	CMP AL,'a'
	JB  L1
	CMP AL,'z'
	JA  L1
	
	XOR DX,DX
	MOV DL,AL
	SUB DL,1 ;变成前导字符
	MOV CX,3
L2: MOV AH,2
	INT 21H
	INC DL
	LOOP L2
    
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

值得注意的一些冷知识:DOS 的2号功能会改变AL中的值!!书上没写!!!
本来想美化一下输入界面的,每输入一个字符程序自动换行,输入合法程序在下一行显示结果;不合法则换行重新输入,但不显示结果。结果程序就出了问题。debug过程中就看到调用2号功能后AL的值发生了改变。点击这个链接可以看到为什么会这样。

5.3 把AX中的16位数按顺序均分为4组,然后把这四组数分别放入AL、BL、CL和DL中

算法分析:就是获取AX中的长度为4的位向量嘛,用屏蔽指令AND可以轻松搞定。唯一麻烦的是,题目要求保存到四个通用寄存器里面,而好多操作都要修改这几个寄存器的值,所以问题是:如何把切割出来的位向量送入四个通用寄存器,而不改变他们的值呢?我的想法是借助堆栈临时保存切割出的位向量,完成所有切割后,再把堆栈中保存的位向量弹出到这四个通用寄存器中

代码:

DATAS SEGMENT
COUNT DB 4     ;需要处理4个数字
DATAS ENDS

STACKS SEGMENT
       DB 30H DUP(0)
   TOP LABEL WORD
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    MOV AX,STACKS
    MOV SS,AX
    MOV SP,TOP
    
    
    MOV AX,6C3BH ;随便什么数都行
    ;算法核心部分;
L1: MOV DX,AX
    AND DX,0FH
    PUSH DX  ;取AX最后四位进栈保存
    
    MOV CL,4
    SHR AX,CL
    DEC COUNT
    CMP COUNT,0 ;这里CX和堆栈都被占用了,不好用LOOP了,所以要用最原始的循环了
    JNE L1
    ; 算法核心部分;
    
    POP AX
    POP BX
    POP CX
    POP DX
    
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值