优化divdw:push si mov si,dx mov bp,ax mov dx,0000h mov ax,si div cx push ax mov ax,bp div cx mov cx,dx pop dx pop si ret
时间: 2024-02-10 19:17:04 浏览: 31
这段代码的作用是将 AX 寄存器中的值除以 CX 寄存器中的值,商存在 CX 中,余数存在 DX 中,并将商和余数同时入栈。优化的话可以考虑使用更高效的指令,比如将 DIV CX 指令替换为 IDIV CX 指令,这样可以同时计算商和余数,避免重复计算。可以改写为:
divdw:
push si
mov si,dx
mov ax,bp
cwd
idiv cx
xchg ax,cx
pop si
ret
其中,CWD 指令用于将 AX 寄存器的值扩展为 DX:AX 的有符号数,IDIV CX 指令用于将 DX:AX 中的值除以 CX,并将商存放在 AX 中,余数存放在 DX 中。最后再将 CX 和 AX 交换位置,使得商在 CX 中,余数在 AX 中,方便后续处理。
相关问题
S0 SEGMENT STACK DW 20 DUP(?) TOP LABEL WORD S0 ENDS S1 SEGMENT TIP DB "Please enter ten numbers separated by spaces:", 0DH, 0AH, 24H ARY DW 20 DUP(0) CRLF DB 0DH, 0AH, 24H N DW 0 S1 ENDS S2 SEGMENT ASSUME SS:S0, DS:S1, CS:S2, ES:S1 P PROC FAR MOV AX, S0 MOV SS, AX LEA SP, TOP MOV AX, S1 MOV DS, AX MOV AX, S1 MOV ES, AX LEA DX, TIP MOV AH, 9 INT 21H LEA SI, ARY XOR DX, DX MOV BL, 10 MOV CX, 10 INPUT: MOV AH, 1 INT 21H CMP AL, 20H ;空格分隔字符 JE SAVE;输入十进制数,将数存入SI对应的内存单元 MOV DL, AL MOV AX, [SI] MUL BL SUB DL, 30H ADD AL, DL MOV [SI], AX JMP INPUT SAVE: ADD SI, 2 LOOP INPUT;数组保存完毕 LEA SI, ARY MOV DI, SI ADD DI, 2 ;DI位于数组的第二元素的位置 MOV BP, 9 ;SI移动的次数和每一次比较的次数,第一次为9 GO: MOV CX, BP ;每一次比较的循环次数 MOV BX, [SI] ;第一个数 CMPA: CMP BX, [DI] ;比较后面的数是否比当前的小 JBE CON ;大于就比较下一个 MOV BX, [DI] ;将寄存器中的值替换为最小的值 MOV AX, DI ;AX存放最小值的偏移地址 CON: ADD DI, 2 LOOP CMPA CMP AX, 0 ;如果AX为0,则表示后面的值没有比当前值小 JE NO ;此时SI加一,移动到第二个数 下一次循环比较开始 CHANGE: MOV DX, [SI] ;78-83行替换当前值与最小值 PUSH DX MOV [SI], BX POP DX MOV DI, AX MOV [DI], DX NO: ADD SI, 2 MOV DI, SI ADD DI, 2 CALL PRINT DEC BP ;循环的次数减一 XOR AX, AX ;清除AX的内容,以便76行判断 CMP BP, 1 JNE GO EXIT: MOV AH, 4CH INT 21H P ENDP PRINT PROC NEAR PUSH SI PUSH CX PUSH AX PUSH DX LEA DX, CRLF MOV AH, 9 INT 21H LEA SI, ARY MOV CX, 10 L1: MOV AX, [SI] MOV N, AX CALL OUTPUT ADD SI, 2 MOV DX, 20H MOV AH, 2 INT 21H LOOP L1 POP DX POP AX POP CX POP SI RET PRINT ENDP OUTPUT PROC NEAR PUSH AX PUSH BX PUSH CX PUSH DX XOR CX, CX MOV AX, N MOV BX, 10 L2: XOR DX, DX DIV BX PUSH DX INC CX CMP AX, 0 JNE L2 L3: POP DX ADD DX, 30H MOV AH, 2 INT 21H LOOP L3 POP DX POP CX POP BX POP AX RET OUTPUT ENDP S2 ENDS END 每行是干什么的P
这是一段汇编代码,实现了一个简单的排序程序。下面是各行代码的功能:
第 1 行:定义 S0 段,用于保存堆栈空间。
第 2 行:定义堆栈中的空间大小,20 个字节,每个字节的初始值为问号。
第 3 行:定义 TOP 标号,用于指向堆栈的顶部。
第 4 行:定义 WORD 类型的 TOP 标号。
第 5 行:定义 S0 段的结束。
第 6 行:定义 S1 段,用于保存提示信息和数组变量。
第 7 行:定义 TIP 变量,用于存储提示信息。
第 8 行:定义 ARY 数组变量,用于保存输入的十个数。
第 9 行:定义 CRLF 变量,用于输出换行符。
第 10 行:定义 N 变量,用于保存输入的数。
第 11 行:定义 S1 段的结束。
第 12 行:定义 S2 段,用于保存程序的主体代码。
第 13 行:假设寄存器 SS 指向 S0 段,DS 和 ES 指向 S1 段,CS 指向 S2 段。
第 14 行:定义 PROC 过程,用于执行排序操作。
第 15 行:将 S0 段的地址存入 AX 寄存器中,再将 AX 中的值存入 SS 寄存器中,将堆栈指针 SP 指向 TOP 标号。
第 16 行:将 S1 段的地址存入 AX 寄存器中,再将 AX 中的值存入 DS 和 ES 寄存器中。
第 17 行:将提示信息的地址存入 DX 寄存器中,设置 AH 寄存器的值为 9,调用 DOS 的 21H 中断,显示提示信息。
第 18 行:将 ARY 数组的地址存入 SI 寄存器中,将 DX 和 BX 寄存器清零,将 BP 寄存器的值设置为 9。
第 19 行:定义标号 GO,用于控制循环次数。
第 20 行:将 BP 寄存器的值存入 CX 寄存器中,用于控制每次比较的循环次数。
第 21 行:将 SI 所指向的数值存入 BX 寄存器中,用于比较后面的数是否比当前的小。
第 22 行:定义标号 CMPA,用于比较后面的数是否比当前的小。
第 23 行:将后面的数与当前的数比较,如果大于等于当前的数,则跳转到标号 CON 继续比较下一个数。
第 24 行:将后面的数与当前的数比较,如果小于当前的数,则将最小值保存在 BX 寄存器中,并将 AX 寄存器的值设置为最小值的偏移地址。
第 25 行:将 DI 寄存器的值加 2,指向下一个数。
第 26 行:循环次数减 1。
第 27 行:跳转到标号 CMPA,继续比较下一个数。
第 28 行:如果 AX 的值为 0,则表示后面的值没有比当前值小,跳转到标号 NO。
第 29 行:将 SI 加 2,移动到第二个数,下一次循环比较开始。
第 30 行:定义标号 CHANGE,用于替换当前值和最小值。
第 31 行:将 SI 所指向的数值存入 DX 寄存器中,将当前值替换为最小值,将最小值替换为当前值,将 DI 寄存器的值设置为最小值的偏移地址。
第 32 行:跳转到标号 NO。
第 33 行:将 SI 加 2,移动到下一个数,将 DI 加 2,移动到下一个需要比较的数。
第 34 行:调用 PRINT 过程,输出排序后的数组。
第 35 行:循环次数减 1。
第 36 行:将 AX 寄存器清零,用于判断循环次数是否为 1。
第 37 行:如果循环次数不为 1,则跳转到标号 GO,继续执行排序操作。
第 38 行:定义 EXIT 标号,用于退出程序。
第 39 行:设置 AH 寄存器的值为 4CH,调用 DOS 的 21H 中断,退出程序。
第 40 行:定义 PRINT 过程,用于输出数组。
第 41 行:将 SI 寄存器的值保存到堆栈中,用于后面恢复现场。
第 42 行:将 CX 寄存器的值保存到堆栈中,用于后面恢复现场。
第 43 行:将 AX 寄存器的值保存到堆栈中,用于后面恢复现场。
第 44 行:将 DX 寄存器的值保存到堆栈中,用于后面恢复现场。
第 45 行:将 CRLF 变量的地址存入 DX 寄存器中,设置 AH 寄存器的值为 9,调用 DOS 的 21H 中断,输出换行符。
第 46 行:将 ARY 数组的地址存入 SI 寄存器中,将 CX 寄存器的值设置为 10,用于输出十个数。
第 47 行:定义标号 L1,用于循环输出十个数。
第 48 行:将 SI 所指向的数值存入 AX 寄存器中。
第 49 行:将 AX 寄存器的值存入 N 变量中,用于后面输出十进制数。
第 50 行:调用 OUTPUT 过程,将 N 变量中的数值输出。
第 51 行:将 SI 加 2,移动到下一个数。
第 52 行:将 20H 存入 DX 寄存器中,设置 AH 寄存器的值为 2,调用 DOS 的 21H 中断,输出空格。
第 53 行:循环次数减 1。
第 54 行:如果循环次数不为 0,则跳转到标号 L1,继续输出数组。
第 55 行:从堆栈中恢复 DX 寄存器的值。
第 56 行:从堆栈中恢复 AX 寄存器的值。
第 57 行:从堆栈中恢复 CX 寄存器的值。
第 58 行:从堆栈中恢复 SI 寄存器的值。
第 59 行:返回到调用 PRINT 过程的指令处。
第 60 行:定义 OUTPUT 过程,用于输出十进制数。
第 61 行:将 AX 寄存器的值保存到堆栈中,用于后面恢复现场。
第 62 行:将 BX 寄存器的值保存到堆栈中,用于后面恢复现场。
第 63 行:将 CX 寄存器的值保存到堆栈中,用于后面恢复现场。
第 64 行:将 DX 寄存器的值保存到堆栈中,用于后面恢复现场。
第 65 行:将 CX 寄存器清零,用于计数。
第 66 行:将 N 变量的值存入 AX 寄存器中,将 10 存入 BX 寄存器中,用于进行除法运算。
第 67 行:定义标号 L2,用于进行除法运算。
第 68 行:将 DX 寄存器清零,用于存储余数。
第 69 行:将 AX 寄存器的值除以 BX 寄存器的值,商存入 AX 中,余数存入 DX 中。
第 70 行:将 DX 寄存器的值存入堆栈中,用于后面恢复现场。
第 71 行:将 CX 寄存器的值加 1,用于计数。
第 72 行:将 AX 寄存器的值与 0 进行比较,如果不为 0,则跳转到标号 L2,继续进行除法运算。
第 73 行:定义标号 L3,用于输出十进制数。
第 74 行:从堆栈中恢复 DX 寄存器的值,将其加上 30H,得到字符的 ASCII 码。
第 75 行:将 DX 寄存器的值存入 AH 寄存器中,设置 AH 寄存器的值为 2,调用 DOS 的 21H 中断,输出字符。
第 76 行:循环次数减 1。
第 77 行:如果循环次数不为 0,则跳转到标号 L3,继续输出十进制数。
第 78 行:从堆栈中恢复 DX 寄存器的值。
第 79 行:从堆栈中恢复 CX 寄存器的值。
第 80 行:从堆栈中恢复 BX 寄存器的值。
第 81 行:从堆栈中恢复 AX 寄存器的值。
第 82 行:返回到调用 OUTPUT 过程的指令处。
第 83 行:定义 OUTPUT 过程的结束。
CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX MAIN: CALL LOP2 LEA DX,HINT_10 MOV AH,09H INT 21H SETCHOOSE: MOV AH,01H INT 21H MOV CHOOSE,AL CALL OUTPUTCRLF CMP CHOOSE,'3' JZ CALL3 CMP CHOOSE,'4' JZ CALL4 CMP CHOOSE,'5' JZ CALL5 CMP CHOOSE,'6' JNZ SETCHOOSE CALL3: CALL LOP3 JMP SETCHOOSE CALL4: CALL LOP4 JMP SETCHOOSE CALL5: CALL LOP5 JMP SETCHOOSE OUTPUT PROC MOV BP,SP MOV AX,[BP+2] MOV INDEX,0 OUTPUT2: CWD DIV TEN ADD DX,30H PUSH DX INC INDEX CMP AX,0 JZ OUTPUT3 JMP OUTPUT2 OUTPUT3: CMP INDEX,0 JZ OUTPUTEND POP DX MOV AH,02H INT 21H DEC INDEX JMP OUTPUT3 OUTPUTEND: RET 2 OUTPUT ENDP OUTPUTSPACE PROC MOV DX,20H MOV AH,02H INT 21H RET OUTPUTSPACE ENDP OUTPUTCRLF PROC LEA DX,CRLF MOV AH,09H INT 21H RET OUTPUTCRLF ENDP LOP5 PROC MOV SI,0 MOV CX,COUNT_3 DEC CX MOV BX,GRADE[SI] ADD AVERAGE,BX ADDSUM: ADD SI,2 MOV BX,GRADE[SI] ADC AVERAGE,BX LOOP ADDSUM LEA DX,HINT_9 MOV AH,09H INT 21H MOV AX,AVERAGE CWD DIV COUNT_3 PUSH DX PUSH AX CALL OUTPUT MOV DX,'.' MOV AH,02H INT 21H MOV CX,COUNT_6 POP AX DECIMAL: MUL TEN CWD DIV COUNT_3 PUSH DX PUSH AX CALL OUTPUT POP AX LOOP DECIMAL CALL OUTPUTCRLF RET LOP5 ENDP LOP4 PROC MOV COUNT_5,0 MOV SI,0 MOV CX,0 COMPARE2: MOV BX,SIXTY CMP GRADE[SI],BX JB ACCOUNT RETURN2: ADD SI,2 INC CX CMP CX,COUNT_3 JNZ COMPARE2 JZ END4 ACCOUNT: INC COUNT_5 JMP RETURN2 END4: LEA DX,HINT_8 MOV AH,09H INT 21H MOV AX,COUNT_5 PUSH AX CALL OUTPUT CALL OUTPUTCRLF RET LOP4 ENDP LOP3 PROC MOV CX,0 FIRST: MOV DI,0 INC CX CMP CX,COUNT_3 JZ OUTPUT_3 COMPARE: MOV BX,GRADE[DI] CMP BX,GRADE[DI+2] JB SWAP RETURN1: ADD DI,2 CMP COUNT_4,DI JZ FIRST JMP COMPARE SWAP: MOV AX,GRADE[DI+2] MOV GRADE[DI],AX MOV GRADE[DI+2],BX JMP RETURN1 OUTPUT_3: MOV CX,COUNT_3 MOV SI,0 OUTPUT0: MOV AX,GRADE[SI] PUSH AX CALL OUTPUT CALL OUTPUTSPACE ADD SI,2 DEC CX CMP CX,0 JNZ OUTPUT0 CALL OUTPUTCRLF RET LOP3 ENDP LOP2 PROC MOV CX,0 MOV SI,0 LEA DX,HINT_6 MOV AH,09H INT 21H INPUT: MOV AH,01H INT 21H CMP AL,0DH JZ SAVENUM CMP AL,' ' JZ SAVENUM MOV DL,AL MOV DH,0 PUSH DI PUSH DX CALL ISDIGITAL POP DX POP DI CMP FLAG_1,0 JZ INPUT MOV N,DX SUB N,30H MOV AX,NUM MUL TEN ADD AX,N MOV NUM,AX JMP INPUT SAVENUM: INC CX MOV BX,NUM MOV GRADE[SI],BX MOV NUM,0 ADD SI,2 CMP AL,0DH JZ END2 JMP INPUT END2: MOV COUNT_3,CX LEA DX,HINT_7 MOV AH,09H INT 21H RET LOP2 ENDP ISDIGITAL PROC MOV BP,SP MOV DI,[BP+2] ISBIGGER: CMP DI,'0' JB NONDIGITAL ISSMALL: CMP DI,'9' JBE DIGITAL JMP NONDIGITAL NONDIGITAL: MOV FLAG_1,0 CALL OUTPUTCRLF LEA DX,HINT_5 MOV NUM,0 MOV AH,09H INT 21H RET DIGITAL: MOV FLAG_1,1 RET ISDIGITAL ENDP MOV AH,4CH INT 21H CODES ENDS END START请用注释的形式为我逐句解释这篇代码的功能
```assembly
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
; 初始化数据段寄存器
START:
MOV AX,DATAS
MOV DS,AX
MAIN:
; 调用 LOP2 过程
CALL LOP2
; 输出提示信息
LEA DX,HINT_10
MOV AH,09H
INT 21H
SETCHOOSE:
; 获取用户输入
MOV AH,01H
INT 21H
MOV CHOOSE,AL
; 根据用户输入调用不同的过程
CALL OUTPUTCRLF
CMP CHOOSE,'3'
JZ CALL3
CMP CHOOSE,'4'
JZ CALL4
CMP CHOOSE,'5'
JZ CALL5
CMP CHOOSE,'6'
JNZ SETCHOOSE
CALL3:
; 调用 LOP3 过程
CALL LOP3
JMP SETCHOOSE
CALL4:
; 调用 LOP4 过程
CALL LOP4
JMP SETCHOOSE
CALL5:
; 调用 LOP5 过程
CALL LOP5
JMP SETCHOOSE
OUTPUT PROC
; 从栈中获取 AX 寄存器中的值
MOV BP,SP
MOV AX,[BP+2]
; 将 AX 中的数字转换成字符并输出
MOV INDEX,0
OUTPUT2:
CWD
DIV TEN
ADD DX,30H
PUSH DX
INC INDEX
CMP AX,0
JZ OUTPUT3
JMP OUTPUT2
OUTPUT3:
CMP INDEX,0
JZ OUTPUTEND
POP DX
MOV AH,02H
INT 21H
DEC INDEX
JMP OUTPUT3
OUTPUTEND:
RET 2
OUTPUT ENDP
OUTPUTSPACE PROC
; 输出一个空格
MOV DX,20H
MOV AH,02H
INT 21H
RET
OUTPUTSPACE ENDP
OUTPUTCRLF PROC
; 输出回车换行
LEA DX,CRLF
MOV AH,09H
INT 21H
RET
OUTPUTCRLF ENDP
LOP5 PROC
; 计算成绩平均值
MOV SI,0
MOV CX,COUNT_3
DEC CX
MOV BX,GRADE[SI]
ADD AVERAGE,BX
ADDSUM:
ADD SI,2
MOV BX,GRADE[SI]
ADC AVERAGE,BX
LOOP ADDSUM
LEA DX,HINT_9
MOV AH,09H
INT 21H
; 输出平均值
MOV AX,AVERAGE
CWD
DIV COUNT_3
PUSH DX
PUSH AX
CALL OUTPUT
MOV DX,'.'
MOV AH,02H
INT 21H
; 输出小数部分
MOV CX,COUNT_6
POP AX
DECIMAL:
MUL TEN
CWD
DIV COUNT_3
PUSH DX
PUSH AX
CALL OUTPUT
POP AX
LOOP DECIMAL
; 输出回车换行
CALL OUTPUTCRLF
RET
LOP5 ENDP
LOP4 PROC
; 查找成绩大于等于 60 分的人数
MOV COUNT_5,0
MOV SI,0
MOV CX,0
COMPARE2:
MOV BX,SIXTY
CMP GRADE[SI],BX
JB ACCOUNT
RETURN2:
ADD SI,2
INC CX
CMP CX,COUNT_3
JNZ COMPARE2
JZ END4
ACCOUNT:
INC COUNT_5
JMP RETURN2
END4:
; 输出人数
LEA DX,HINT_8
MOV AH,09H
INT 21H
MOV AX,COUNT_5
PUSH AX
CALL OUTPUT
CALL OUTPUTCRLF
RET
LOP4 ENDP
LOP3 PROC
; 排序并输出成绩
MOV CX,0
FIRST:
MOV DI,0
INC CX
CMP CX,COUNT_3
JZ OUTPUT_3
COMPARE:
MOV BX,GRADE[DI]
CMP BX,GRADE[DI+2]
JB SWAP
RETURN1:
ADD DI,2
CMP COUNT_4,DI
JZ FIRST
JMP COMPARE
SWAP:
MOV AX,GRADE[DI+2]
MOV GRADE[DI],AX
MOV GRADE[DI+2],BX
JMP RETURN1
OUTPUT_3:
MOV CX,COUNT_3
MOV SI,0
OUTPUT0:
MOV AX,GRADE[SI]
PUSH AX
CALL OUTPUT
CALL OUTPUTSPACE
ADD SI,2
DEC CX
CMP CX,0
JNZ OUTPUT0
CALL OUTPUTCRLF
RET
LOP3 ENDP
LOP2 PROC
; 输出提示信息
MOV CX,0
MOV SI,0
LEA DX,HINT_6
MOV AH,09H
INT 21H
INPUT:
; 获取用户输入
MOV AH,01H
INT 21H
CMP AL,0DH
JZ SAVENUM
CMP AL,' '
JZ SAVENUM
MOV DL,AL
MOV DH,0
PUSH DI
PUSH DX
CALL ISDIGITAL
POP DX
POP DI
CMP FLAG_1,0
JZ INPUT
MOV N,DX
SUB N,30H
MOV AX,NUM
MUL TEN
ADD AX,N
MOV NUM,AX
JMP INPUT
SAVENUM:
INC CX
MOV BX,NUM
MOV GRADE[SI],BX
MOV NUM,0
ADD SI,2
CMP AL,0DH
JZ END2
JMP INPUT
END2:
MOV COUNT_3,CX
LEA DX,HINT_7
MOV AH,09H
INT 21H
RET
LOP2 ENDP
ISDIGITAL PROC
; 判断字符是否为数字
MOV BP,SP
MOV DI,[BP+2]
ISBIGGER:
CMP DI,'0'
JB NONDIGITAL
ISSMALL:
CMP DI,'9'
JBE DIGITAL
JMP NONDIGITAL
NONDIGITAL:
MOV FLAG_1,0
CALL OUTPUTCRLF
LEA DX,HINT_5
MOV NUM,0
MOV AH,09H
INT 21H
RET
DIGITAL:
MOV FLAG_1,1
RET
ISDIGITAL ENDP
; 程序结束
MOV AH,4CH
INT 21H
CODES ENDS
END START
```
这段代码是一个简单的成绩管理程序,可以实现以下功能:
1. 输入成绩,最多输入 30 个,保存在数组 `GRADE` 中。
2. 对成绩进行排序并输出。
3. 计算成绩平均值,输出平均值及小数部分。
4. 查找成绩大于等于 60 分的人数,输出人数。
程序的具体实现细节可以参考注释。
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![docx](https://img-home.csdnimg.cn/images/20210720083331.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)