5.6 编写程序,将一个包含有 20 个数据的数组 M 分成两个数组:正数数组 P 和负数数组 N,
并分别把这两个数组中数据的个数显示出来。
DATAS SEGMENT
STR1 DW 1,-1,-2,8,-9,-8,2,7,11,12,78,65,-12,10,19,23,5,-7,77,88
N_COU DW 0 ;记录负数的个数
P_COU DW 0 ;记录正数的个数
N DW 14H DUP(?) ;存放负数
P DW 14H DUP(?) ;存放正数
DATAS ENDS
STACKS SEGMENT
DW 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 ES,AX
MOV AX,STACKS
MOV SS,AX
LEA SP,TOP
LEA SI,STR1
MOV BX,0 ;用于偏移N数组的地址
MOV DI,0 ;用于偏移P数组的地址,DI是偏移量,初始化为0
;DI怎么在P和N数组之间进行转化:开两个寄存器记录
MOV CX,14H
L1: PUSH CX ;循环20次
MOV AX,[SI]
CMP AX,0 ;比较是否大于0
JG P_CODE ;大于0存储到P数组
;负数
MOV N[BX],AX ;把数字存放到N数组里
ADD BX,02H ;指针后移两个字节
INC N_COU
JMP NEXT
P_CODE:
;正数
MOV P[DI],AX ;!!!注意这里DI的使用方法
ADD DI,02H
INC P_COU
NEXT:
ADD SI,02H ;源串的指针后移两个字节
POP CX
LOOP L1
OUT_PUT:
MOV AX,P_COU ;正数
CALL PRINT
MOV AH,02H
MOV DL,0AH
INT 21H
MOV AX,N_COU ;负数
CALL PRINT
;此处输入代码段代码
MOV AH,4CH
INT 21H
;十进制数的输出,除10取余输出
PRINT PROC
MOV CX,0
PL1:MOV DX,0 ;清零操作
MOV SI,10
DIV SI
PUSH DX ;把余数入栈
INC CX ;统计数位,便于L2执行输出
CMP AX,0
JNE PL1 ;商不为0
PL2:POP DX
ADD DX,30H ;转化为字符类型,为输出做准备
MOV AH,02H
INT 21H
LOOP PL2
RET
PRINT ENDP
CODES ENDS
END START
5.7 试编写一个汇编语言程序,求出首地址为 DATA 的 100D 字数组中的最小偶数,并把它
存放在 AX 中。(此处我的数组中仅有10个数值)
思路:
- 使用SI指针来遍历数组A
- 初始化AX为极大值来与指针SI所指向的数值比较,每次取更小的偶数
- 最后使用十进制输出,验证是否正确
要点:
- 特殊处理0值(优化了代码,不加也可以)
- 注意保护AX的数值
- 利用TEST来测试当前数字是偶数还是奇数。TEST用于按位与操作,若结果为0,则ZF=1;反之,ZF=0
DATAS SEGMENT
A DW 9,11,12,16,7,3,4,15,99,78 ;定义一个数组
;DW 90 DUP(?)
DATAS ENDS
STACKS SEGMENT
DW 100 DUP(?)
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
LEA SP,TOP
LEA SI,A ;SI指向A数组的首地址
MOV CX,10
MOV AX,0FFFH ;初始化为最大有符号数
FIND_MIN:
MOV BX,[SI]
TEST BX,1 ;测试最低位是否为1,将BX与1按位与,如果结果为0,则ZF=1;反之,ZF=0
JNZ NEXT_OP ;说明是奇数
CMP BX,AX
JGE NEXT_OP ;有符号,>=
MOV AX,BX
; 在FIND_MIN循环后添加
NEXT_OP:
ADD SI,2
LOOP FIND_MIN
;输出验证
MOV BX,AX ;要输出的数
MOV CX,0
;处理0的特殊情况
CMP BX,0
JNE OUT_PUT
MOV DL,'0'
MOV AH,02H
INT 21H
JMP EXIT
MOV AX,BX ;恢复AX的数值
OUT_PUT:
MOV DX,0 ;DX清零
MOV SI,10
DIV SI
PUSH DX ;存余数
INC CX
CMP AX,0 ;比较商值
JNE OUT_PUT
PRINT_OP:
POP DX
ADD DL,30H ;转化为字符型
MOV AH,02H
INT 21H
LOOP PRINT_OP
;结束
EXIT:
MOV AH,4CH
INT 21H
CODES ENDS
END START
5.8 把 AX 中存放的 16 位二进制数 K 看作是 8 个二进制的“四分之一字节”。试编写程序
要求数一下值为 3(即 11B)的四分之一字节数,并将该数(即 11B 的个数)在终端上显示出来
DATAS SEGMENT
NUM DW 0 ;存放11的个数
A DW 55 ;0000 0000 0011 0111
DATAS ENDS
STACKS SEGMENT
DW 30H DUP(?)
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
LEA SP,TOP
MOV CX,8
MOV AX,A
L1: PUSH CX
MOV CL,2
ROL AX,CL ;注意移位操作
MOV DX,AX
AND DX,03H
;比较是否等于3
CMP DX,03H ;直接比较即可,不用ADD DX,30H,取出来时已经是数字类型
JNE NEXT
INC NUM
NEXT:
POP CX
LOOP L1
PRINT:;结果不超过8
MOV DX,NUM
ADD DL,30H
MOV AH,02H
INT 21H
;结束
MOV AH,4CH
INT 21H
CODES ENDS
END START
5.9 试编写一个汇编语言程序,要求从键盘接收一个四位的 16 进制数,并在终端上显示与
它等值的二进制数
要点:
- 输入的范围为0-9,a-f(在doxbos上不知道为什么不能采用大写)
- 16进制输入存入DX,每次输入存在AL中,然后先左移DX,再ADD DX,AX,注意要对AH清零,否则就要出错
- 二进制输出:即0或1的输出
- 还要注意在把数值存放在DX中时,有时候可能在使用INT 21H功能时,对DX,AX造成了变化,所以输入结束后要尽快保存NUM
DATAS SEGMENT
NUM DW ?
DATAS ENDS
STACKS SEGMENT
DW 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
LEA SP,TOP
;输入16进制的4位数
MOV DX,0
MOV AX,0
MOV CX,4
L1: PUSH CX
MOV AH,01H
INT 21H
CMP AL,'0' ;小于0说明非法
JB L1
CMP AL,'9' ;大于9转入判断是否为A-F
JBE NEXT
L2: CMP AL,'a' ;用大写没办法正确检验
JB L1
CMP AL,'f'
JA L1
SUB AL,27H ;A-F
NEXT:
SUB AL,30H ;说明输入的数值在0-9范围
L3: MOV CL,4
AND AL,0FH ;仅保留低四位!!!
SHL DX,CL ;把DX左移四位
MOV AH,0 ;!!!!!!!!为什么要清零
ADD DX,AX ;存放到DL中
POP CX
LOOP L1
;读取输入的字符
L4: MOV NUM,DX
MOV BX,NUM
MOV CX,16
MOV AH,02H
MOV DL,0AH
INT 21H ;输出换行符,美化格式
NEXT_2:
PUSH CX
ROL BX,1 ;循环左移1位
MOV DX,BX
AND DX,01H ;取最低位,用二进制输出
ADD DX,30H ;转化为字符类型
MOV AH,02H
INT 21H
POP CX
LOOP NEXT_2
;此处输入代码段代码
MOV AH,4CH
INT 21H
CODES ENDS
END START
453

被折叠的 条评论
为什么被折叠?



