每天一到汇编题(4)

博主是个大笨比,只会阿巴阿巴阿巴

题目

已知数据定义如下,编程统计str字节单元中奇数的个数,并把数存入result单元

Data SEGMENT
	str DB 51,30,43,107,89,90,200,27,70,66
	result DB ?
Data ENDS

注意:由于博主的电脑如果使用 str 作为变量名称会报错:

errorA2085 instruction or register not accepted in current CPU mode
指令或寄存器在当前CPU模式下不被接受

若使用其他变量名如 Abits 则编译通过,博主也并没有查到解决办法,如果有人知道解决方法,请评论说明,我在这里表示感谢 Thanks♪(・ω・)ノ 。

指令意思
LEA (指令)将源操作数的有效偏移地址传递给寄存器
offect(操作符)取出标号或变量在段内的偏移地址 (有时 与LEA 所表达的效果相同)
SHR逻辑右移
CWB字节扩展指令,将AL扩展至AH,如果D7 = 0 则 AH 为 0 否则 AX 为 0FFH
JNB(或者 JAE)如果 CF = 0 则 跳转
test用来判断某位是否为0 ,若ZF为1 则表明 某位为0 否则某位就是1
JZ若 ZF = 1 则跳转
DIV格式为 DIV SRC 如果SRC为字节 默认被除数在AX中,得到的8位商在AL中 余数在AH中
CMP比较两数字是否相同,只影响标志位,不回传结果,如果相同 则ZF = 0

思路一(通过移位实现)

仔细观察这里面的数

  1. 奇数:51,43,107,89,27
  2. 偶数:30,90,200,70,66

奇数二进制(基2码 ):
51: 0011 0011
43: 0010 1011
107:0110 1011
89: 0101 1001
27: 0001 1011

偶数二进制:
30: 0001 1110
90 0101 1010
200 1100 1000
70 0100 0110
66 0100 0010

奇数的最后一位都是 1 如果我们将其移动到CF中并判断其值 变可以分辨其是奇数还是偶数

Data SEGMENT
	Abits DB 51,30,43,107,89,90,200,27,70,66
	RESULT DB ?
Data ENDS
Code SEGMENT
	ASSUME CS:Code,DS:Data
Start:
	MOV AX,Data
	MOV DS,AX
	;================================================================
	LEA BX,Abits ;取出Abits的有效偏移地址
	MOV RESULT,0 ;将RESULT的初始值赋值为0
	MOV CX,10    ;循环次数为10
Judge: 
 	MOV AH,0     ;将AX的最高位赋值为0 (这里其实就是为了数据的美观,好看)
	MOV AL,[BX]  ;读取Abits中的值 赋给 al 
	INC BX       ;使BX内容+1  地址内容 +1 
	SHR AX,1     ;逻辑左移
	JNB Next 	 ;判断是否为 0 如果是则开始下一次循环,否则就向下执行
	INC RESULT	 ;使RESULT的值 +1 
	;================================================================
Next:
	LOOP Judge   ;循环
Exit:
	MOV AH,0     ;将AX的最高位赋值为0 (这里其实就是为了数据的美观,好看)
	MOV AL,RESULT;将RESULT中的值赋值给AL (其实就是可以在DEBUG中更容易看到得数)
	MOV AH,4CH
	INT 21H
Code ENDS
END Start

思路二(利用Test指令的特性)

Data SEGMENT
	Abits DB 51,30,43,107,89,90,200,27,70,66
	RESULT DB ?
Data ENDS
Code SEGMENT
	ASSUME CS:Code,DS:Data
Start:
	MOV AX,Data
	MOV DS,AX
	;================================================================
	MOV BL,0     ;将BL的值清0
	LEA SI,ABITS ;将SI寄存器的值 赋值为 变量的有效地址
	MOV CX,10    ;循环次数为10
Judge:
	MOV AL,[SI]  ;将地址中的值赋值给al寄存器
	TEST AL,01H  ;test 指令 实际就是两个操作数相与 但结果并不赋值给目的操作数
	JZ Next      ;如果ZF为0 则 跳转至 Next
	INC BL       ;BL值加一
Next:
	INC SI       ;地址+1
	LOOP Judge
	MOV RESULT,BL;将BL的值赋值给RESULT
	;================================================================
	MOV AH,4CH
	INT 21H
Code ENDS
END Start

思路三(最先想到的复杂思路 使用DIV 做 除法)

Data SEGMENT
	Abits DB 51,30,43,107,89,90,200,27,70,66
	RESULT DB ?
Data ENDS
Code SEGMENT
	ASSUME CS:Code,DS:Data
Start:
	MOV AX,Data
	MOV DS,AX
	;================================================================
	MOV BX,OFFSET Abits ;求 Abits 在DS中的有效地址
	MOV RESULT,0        ;将 RESULT 赋值为0
	MOV DL,2			;将除数设置为2
	MOV CX,10           ;循环次数为10
Judge:
	MOV AL,[BX]         ;将Abits中的值依次赋值给AL
	;这里不使用CBW是因为 如果D7位1 则AH 就变为了0FFH,除法就会出错
	MOV AH,0			;将AH赋值为0 
	ADD BX,1			;使地址+1
	DIV DL              ;因为被除数是字节 所以 被除数在AX中 得到的商在AL中 余数在AH中
	CMP AH,0            ;比较AH与0
	JZ Next             ;如果能除尽则AH为0,ZF为1,则继续下一个数
	INC RESULT          ;奇数加一
Next:
	LOOP Judge
	;================================================================
Exit:
	MOV DH,0            ;将DH清0 只为数据更好看
	MOV DL,RESULT       ;将结果赋值给DL 这样可以在DEBUG中方便的看到结果
	MOV AH,4CH
	INT 21H
Code ENDS
END Start
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值