北理的汇编期末题其实也没太大难度,很多三星题都是C里面写过的非常容易的题目,而且因为允许提前准备,所以难度又降低了很多,我下面的代码基本上都是自己敲得(不排除有一些算法去网上搜了一下借鉴了一下别人的),另外不完全排除留有bug的可能性,因为我也不是每个用例都测试过了。
也可以看出我这个人的风格,就是喜欢疯狂开堆栈,疯狂写子程序,能封装的东西就一直封装到祖坟里去,毕竟我搞嵌入式软件搞得比较多,那种能封装就封装的工程思想就算是写这种百来行的代码也很难改掉习惯。
在多模块设计中,主模块中调用内部模块buf1,buf2,buf3,buf4。主模块根据键盘输入的指令(如:a,b,c,d)调用上述对应的子程序,每个子程序的任务是显示其入口地址。调用后继续等待调用,若输入ESC键(ASCII码为1BH)则结束程序的执行。请编写完成该任务的程序。
没有什么特别难的地方,主要是得注意一下DISPLAY那边的写法
MOV CL,04H ROL BX,CL ;只能用CL做循环移位,每次移动4位 AND AX,0FH ;取低4位,然后单独打印
打印字母要用到ADD 07H
入口获取就直接在DATA SEGMENT里面声明DW的几个变量,然后声明PROC的时候用它们就行了
DATA SEGMENT
BUF DB 10
DB ?
DB 10 DUP('$')
NEWLINE DB 0DH,0AH,'$'
OUTPUT DW BUF1,BUF2,BUF3,BUF4
DATA ENDS
STACKS SEGMENT STACK
DB 100 DUP(0)
STACKS ENDS
CODE SEGMENT
ASSUME DS:DATA,CS:CODE,SS:STACKS
START:
MOV AX,DATA
MOV DS,AX
MOV DX,STACKS
MOV SS,DX
INPUT:
MOV AH,0AH
LEA DX,BUF
INT 21H
MOV SI,OFFSET BUF
ADD SI,02H
MOV AL,[SI]
JUDGE:
CMP AL,'a'
JE ISA
CMP AL,'b'
JE ISB
CMP AL,'c'
JE ISC
CMP AL,'d'
JE ISD
CMP AL,1BH
JE BREAK
JMP INPUT
BREAK:
MOV AH,4CH
INT 21H
ISA:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
CALL BUF1
JMP INPUT
ISB:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
CALL BUF2
JMP INPUT
ISC:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
CALL BUF3
JMP INPUT
ISD:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
CALL BUF4
JMP INPUT
;子程序调用
BUF1 PROC
MOV BX,OFFSET BUF1
CALL DISPLAY
RET
BUF1 ENDP
BUF2 PROC
MOV BX,OFFSET BUF2
CALL DISPLAY
RET
BUF2 ENDP
BUF3 PROC
MOV BX,OFFSET BUF3
CALL DISPLAY
RET
BUF3 ENDP
BUF4 PROC
MOV BX,OFFSET BUF4
CALL DISPLAY
RET
BUF4 ENDP
;显示
DISPLAY PROC
PUSH AX
PUSH CX
PUSH DX
MOV CH,04H
MOV CL,04H
TURN:
ROL BX,CL
MOV AL,BL
AND AL,0FH
CMP AL,9
JBE NUM
;否则是字母
MOV DL,AL
ADD DL,37H
MOV AH,02H
INT 21H
DEC CH
JZ DONE
JMP TURN
NUM:
MOV DL,AL
ADD DL,'0'
MOV AH,02H
INT 21H
DEC CH
JZ DONE
JMP TURN
DONE:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
POP DX
POP CX
POP AX
RET
DISPLAY ENDP
CODE ENDS
END START
现有一控制程序共5个工序,要求输入04的序号,分别执行各工序的子程序,每个子程序的任务是显示其入口地址。调用后继续等待调用,按回车则结束程序的执行。
这个和第一题有个jb的区别啊
DATA SEGMENT
BUF DB 10
DB ?
DB 10 DUP('$')
NEWLINE DB 0DH,0AH,'$'
OUTPUT DW BUF1,BUF2,BUF3,BUF4,BUF5
DATA ENDS
STACKS SEGMENT STACK
DB 100 DUP(0)
STACKS ENDS
CODE SEGMENT
ASSUME DS:DATA,CS:CODE,SS:STACKS
START:
MOV AX,DATA
MOV DS,AX
MOV DX,STACKS
MOV SS,DX
INPUT:
MOV AH,0AH
LEA DX,BUF
INT 21H
MOV SI,OFFSET BUF
ADD SI,02H
MOV AL,[SI]
JUDGE:
CMP AL,'0'
JE ISA
CMP AL,'1'
JE ISB
CMP AL,'2'
JE ISC
CMP AL,'3'
JE ISD
CMP AL,'4'
JE ISE
CMP AL,0DH
JE BREAK
JMP INPUT
BREAK:
MOV AH,4CH
INT 21H
ISA:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
CALL BUF1
JMP INPUT
ISB:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
CALL BUF2
JMP INPUT
ISC:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
CALL BUF3
JMP INPUT
ISD:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
CALL BUF4
JMP INPUT
ISE:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
CALL BUF5
JMP INPUT
;子程序调用
BUF1 PROC
MOV BX,OFFSET BUF1
CALL DISPLAY
RET
BUF1 ENDP
BUF2 PROC
MOV BX,OFFSET BUF2
CALL DISPLAY
RET
BUF2 ENDP
BUF3 PROC
MOV BX,OFFSET BUF3
CALL DISPLAY
RET
BUF3 ENDP
BUF4 PROC
MOV BX,OFFSET BUF4
CALL DISPLAY
RET
BUF4 ENDP
BUF5 PROC
MOV BX,OFFSET BUF5
CALL DISPLAY
RET
BUF5 ENDP
;显示
DISPLAY PROC
PUSH AX
PUSH CX
PUSH DX
MOV CH,04H
MOV CL,04H
TURN:
ROL BX,CL
MOV AL,BL
AND AL,0FH
CMP AL,9
JBE NUM
;否则是字母
ADD AL,07H
MOV AH,02H
INT 21H
DEC CH
JZ DONE
JMP TURN
NUM:
MOV DL,AL
ADD DL,'0'
MOV AH,02H
INT 21H
DEC CH
JZ DONE
JMP TURN
DONE:
MOV AH,09H
MOV DX,OFFSET NEWLINE
INT 21H
POP DX
POP CX
POP AX
RET
DISPLAY ENDP
CODE ENDS
END START
现有一组字符串为data,name,time,file,code,path,user,exit,quit,text,请编写程序从键盘输入4个字符的字符串,若存在将其修改为disk, 并将结果在显示器上显示。
好好用子程序和堆栈就能解决大部分的问题,这里主要是先把算法想清楚了问题就简单很多,
DATA SEGMENT
INPUTBUF DB 10
DB ?
DB 10 DUP('$')
BUF DB 'data',',','name',',','time',',','file',',','code',',','path',',','user',',','exit',',','quit',',','text','$'
REPLACE DB 'disk'
BUFTOCMP DB 4 DUP('$')
NEWLINE DB 0AH,0DH,'$'
DATA ENDS
STACKS SEGMENT STACK
DW 100 DUP('$')
STACKS ENDS
CODE SEGMENT
ASSUME DS:DATA,CS:CODE,SS:STACKS
START:
MOV AX,DATA
MOV DS,AX
MOV DX,STACKS
MOV SS,DX
MOV AH,0AH
LEA DX,INPUTBUF
INT 21H
MOV CH,00H
MOV CL,0AH
MOV SI,OFFSET BUF
WORK:
CALL PASTE
CALL COMPARE
BREAK:
ADD SI,05H
LOOP WORK
RESULT:
;输出
CALL DISPLAY
MOV AH,4CH
INT 21H
;子程序段
;从BUF中赋值到BUFTOCMP
PASTE PROC
PUSH DI
PUSH AX
PUSH CX
PUSH SI
MOV CH,00H
MOV CL,04H
MOV DI,OFFSET BUFTOCMP
A:
MOV AL,[SI]
MOV [DI],AL
INC DI
INC SI
LOOP A
POP SI
POP CX
POP AX
POP DI
RET
PASTE ENDP
;将INPUTBUF中的数据和BUFTOCMP进行比较
COMPARE PROC
PUSH SI
PUSH DI
PUSH CX
PUSH AX
PUSH BX
MOV SI,OFFSET BUFTOCMP
MOV DI,OFFSET INPUTBUF
ADD DI,02H
MOV CH,00H
MOV CL,04H
B:
MOV AL,[SI]
MOV BL,[DI]
INC SI
INC DI
CMP AL,BL
JNE NOTEUQL
LOOP B
;说明找到的一致,进行交换
POP BX
POP AX
POP CX
POP DI
POP SI
CALL EXCHANGE
NOTEUQL:
POP BX
POP AX
POP CX
POP DI
POP SI
JMP BREAK
RET
COMPARE ENDP
;显示
DISPLAY PROC
PUSH DX
PUSH AX
MOV DX,OFFSET NEWLINE
MOV AH,09H
INT 21H
MOV DX,OFFSET BUF
MOV AH,09H
INT 21H
POP AX
POP DX
RET
DISPLAY ENDP
;进行交换
EXCHANGE PROC
PUSH DI
PUSH CX
PUSH AX
MOV CH,00H
MOV CL,04H
MOV DI,OFFSET REPLACE
C:
MOV AL,[DI]
MOV [SI],AL
INC SI
INC DI
LOOP C
;交换完就不再循环,直接退出打印
JMP RESULT
POP AX
POP CX
POP DI
POP SI
RET
EXCHANGE ENDP
CODE ENDS
END START
现有一组字符串为data,name,time,file,code,path,user,exit,quit,text,请编写程序从键盘输入4个字符的字符串,若存在将其删除, 并在显示器上显示。
同样和上一道题没有jb差别,这里是删除,所以设计子程序为:
1.把buf中的值粘贴到buftocmp
2.和输入值比较
3.如果不相等则paste到outputbuf中
4.如果相等就跳回原来的工作循环
太简单所以几分钟就改完了
DATA SEGMENT
INPUTBUF DB 10
DB ?
DB 10 DUP('$')
BUF DB 'data',',','name',',','time',',','file',',','code',',','path',',','user',',','exit',',','quit',',','text','$'
BUFTOCMP DB 4 DUP('$')
NEWLINE DB 0AH,0DH,'$'
OUTPUTBUF DB 8 DUP(4 DUP('$'),','),4 DUP('$'),'$'
DATA ENDS
STACKS SEGMENT STACK
DW 100 DUP('$')
STACKS ENDS
CODE SEGMENT
ASSUME DS:DATA,CS:CODE,SS:STACKS
START:
MOV AX,DATA
MOV DS,AX
MOV DX,STACKS
MOV SS,DX
MOV AH,0AH
LEA DX,INPUTBUF
INT 21H
MOV CH,00H
MOV CL,0AH
MOV SI,OFFSET BUF
MOV DI,OFFSET OUTPUTBUF
WORK:
CALL PASTE
CALL COMPARE
ADD DI,05H
BREAK:
ADD SI,05H
LOOP WORK
RESULT:
;输出
CALL DISPLAY
MOV AH,4CH
INT 21H
;子程序段
;从BUF中赋值到BUFTOCMP
PASTE PROC
PUSH DI
PUSH AX
PUSH CX
PUSH SI
MOV CH,00H
MOV CL,04H
MOV DI,OFFSET BUFTOCMP
A:
MOV AL,[SI]
MOV [DI],AL
INC DI
INC SI
LOOP A
POP SI
POP CX
POP AX
POP DI
RET
PASTE ENDP
;将INPUTBUF中的数据和BUFTOCMP进行比较
COMPARE PROC
PUSH SI
PUSH DI
PUSH CX
PUSH AX
PUSH BX
MOV SI,OFFSET BUFTOCMP
MOV DI,OFFSET INPUTBUF
ADD DI,02H
MOV CH,00H
MOV CL,04H
B:
MOV AL,[SI]
MOV BL,[DI]
INC SI
INC DI
CMP AL,BL
;说明找到的一致,进行交换
JNE NOTEUQL
LOOP B
POP BX
POP AX
POP CX
POP DI
POP SI
JMP BREAK
NOTEUQL:
POP BX
POP AX
POP CX
POP DI
POP SI
CALL COPY
RET
COMPARE ENDP
;显示
DISPLAY PROC
PUSH DX
PUSH AX
MOV DX,OFFSET NEWLINE
MOV AH,09H
INT 21H
MOV DX,OFFSET OUTPUTBUF
MOV AH,09H
INT 21H
POP AX
POP DX
RET
DISPLAY ENDP
COPY PROC
PUSH SI
PUSH DI
PUSH CX
PUSH AX
MOV CH,00H
MOV CL,04H
C:
MOV AL,[SI]
MOV [DI],AL
INC SI
INC DI
LOOP C
POP AX
POP CX
POP DI
POP SI
RET
COPY ENDP
CODE ENDS
END START
一个有符号字数组以0为结束标志,编程求这个数组的最大值、 最小值、平均值。
数组长度闭着眼睛就能弄到
求最大值最小值也很无脑,拿个buf放在那边,一个一个去比大小就行了
求平均值依然无脑,求和然后除一下长度就结束了
算除法的时候得把和放到AX中,最好用IDIV,这里是正数,所以结果反正是一样的
DATA SEGMENT BUF DB 0D5H,21H,0A3H,83H,70H,00H LEN EQU $BUF MAX DB 00H,'$' MIN DB 00H,'$' AVER DB 00H,',',00H,'$' NEWLINE DB 0AH,0DH,'$' DATA ENDS STACKS SEGMENT STACK DW 100 DUP(0) STACKS ENDS CODE SEGMENT ASSUME DS:DATA,CS:CODE,SS:STACKS START: MOV AX,DATA MOV DS,AX MOV DX,STACKS MOV SS,DX MOV SI,OFFSET BUF ;获取数组长度 MOV CH,00H MOV CL,LEN DEC CL ;找最大数 CALL FINDMAX ;找最小数 CALL FINDMIN ;求平均值 CALL AVERAGE ;显示 CALL DISPLAY MOV AH,4CH INT 21H ;子程序段 ;找最大值 FINDMAX PROC PUSH AX PUSH CX PUSH SI PUSH DI MOV DI,OFFSET MAX MOV AL,[SI] MOV [DI],AL A: CMP AL,[SI] JL MAXEXCHANGE INC SI LOOP A JMP MAXDONE MAXEXCHANGE: MOV AL,[SI] MOV [DI],AL INC SI LOOP A MAXDONE: POP DI POP SI POP CX POP AX RET FINDMAX ENDP ;找最小值 FINDMIN PROC PUSH AX PUSH CX PUSH SI PUSH DI MOV DI,OFFSET MIN MOV AL,[SI] MOV [DI],AL B: CMP AL,[SI] JG MINEXCHANGE INC SI LOOP B JMP MINDONE MINEXCHANGE: MOV AL,[SI] MOV [DI],AL INC SI LOOP B MINDONE: POP DI POP SI POP CX POP AX RET FINDMIN ENDP ;求平均 AVERAGE PROC PUSH AX PUSH CX PUSH SI PUSH DI PUSH BX MOV AL,00H MOV AH,00H ;先求和 C: MOV BL,[SI] ADD AL,BL ADC AH,00H INC SI LOOP C MOV CL,LEN ;再求平均 DIV CL ;AL中为商,AH中为余数 MOV DI,OFFSET AVER MOV [DI],AL ADD DI,02H MOV [DI],AH POP BX POP DI POP SI POP CX POP AX RET AVERAGE ENDP ;显示,这个又要用到和第一题一样的技巧了,运用循环右移的方式把结果输出出来 DISPLAY PROC ;打印最大值 MOV CH,00H MOV CL,04H MOV BL,02H MOV DI,OFFSET MAX MOV CH,[DI] D: ROL CH,CL MOV DL,CH AND DL,0FH CMP DL,09H JB NUM ADD DL,37H MOV AH,02H INT 21H DEC BL JNZ D JMP MINPRINT NUM: ADD DL,'0' MOV AH,02H INT 21H DEC BL JNZ D MINPRINT: MOV AH,09H MOV DX,OFFSET NEWLINE INT 21H MOV CH,00H MOV CL,04H MOV BL,02H MOV DI,OFFSET MIN MOV CH,[DI] E: ROL CH,CL MOV DL,CH AND DL,0FH CMP DL,09H JB MINNUM ADD DL,37H MOV AH,02H INT 21H DEC BL JNZ E JMP AVERPRINT MINNUM: ADD DL,'0' MOV AH,02H INT 21H DEC BL JNZ E AVERPRINT: MOV AH,09H MOV DX,OFFSET NEWLINE INT 21H MOV CH,00H MOV CL,04H MOV BL,02H MOV DI,OFFSET AVER MOV CH,[DI] F: ROL CH,CL MOV DL,CH AND DL,0FH CMP DL,09H JB AVERNUM ADD DL,37H MOV AH,02H INT 21H DEC BL JNZ F JMP ENDING AVERNUM: ADD DL,'0' MOV AH,02H INT 21H DEC BL JNZ F ENDING: RET DISPLAY ENDP CODE ENDS END START
在BUFFER中定义了的十个带符号字,将其中的负数变成绝对值,并以十进制方式输出。
……这种弱智东西也好意思出成三星题
遍历,和0比判断是不是负数
将负数变成绝对值:取补码,结束
用十进制输出:遍历,做十进制调整,游戏结束
DATA SEGMENT BUF DB 0AH,31H,63H,53H,7EH,88H,0EEH,0DCH,0A2H,0C8H LEN EQU $BUF DATA ENDS STACKS SEGMENT STACK DW 100 DUP(?) STACKS ENDS CODE SEGMENT ASSUME DS:DATA,CS:CODE,SS:STACKS START: MOV AX,DATA MOV DS,AX MOV DX,STACKS MOV SS,DX MOV CH,00H MOV CL,LEN MOV SI,OFFSET BUF ;将所有负数变成绝对值 CALL ABSLUTE ;将结果输出 CALL OUTPUT MOV AH,4CH INT 21H ;子程序段 ABSLUTE PROC PUSH CX PUSH SI A: MOV AL,[SI] CMP AL,0 JL TURNPOSITIVE INC SI LOOP A JMP DONE TURNPOSITIVE: NOT AL ADD AL,01H MOV [SI],AL LOOP A DONE: POP SI POP CX RET ABSLUTE ENDP ;转变为十进制数 OUTPUT PROC PUSH CX PUSH SI PUSH AX PUSH BX PUSH DX MOV SI,OFFSET BUF B: MOV AL,[SI] ADD AL,00H DAA MOV [SI],AL INC SI LOOP B ;进行输出 MOV BH,00H MOV BL,LEN MOV CH,00H MOV CL,04H MOV SI,OFFSET BUF C: MOV CH,[SI] ROL CH,CL MOV DL,CH AND DL,0FH ADD DL,'0' MOV AH,02H INT 21H ROL CH,CL MOV DL,CH AND DL,0FH ADD DL,'0' MOV AH,02H INT 21H MOV DL,',' MOV AH,02H INT 21H INC SI DEC BL JNZ C POP DX POP BX POP AX POP SI POP CX RET OUTPUT ENDP CODE ENDS END START
已知数组A包含20个互不相等的字型整数,数组B包含30个互不相等的字型整数,试编制一程序把在A中而不在B中出现的整数放于数组C中。
这个挺C的……用汇编来做……也差不多
算法很简单,嵌套循环即可,每查阅一次A的一个单元,就遍历一次B,找B中有没有出现,如果出现了就跳过,没出现的话就复制到C中
就是无脑的双层循环,直接KO
DATA SEGMENT
BUFA DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
BUFB DB 11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
BUFC DB 50 DUP('$')
DATA ENDS
STACKS SEGMENT STACK
DW 100 DUP(0)
STACKS ENDS
CODE SEGMENT
ASSUME DS:DATA,CS:CODE,SS:STACKS
START:
MOV AX,DATA
MOV DS,AX
MOV DX,STACKS
MOV SS,DX
;外层循环BUFA
MOV CX,20
MOV SI,OFFSET BUFA
MOV DI,OFFSET BUFC
A:
MOV AL,[SI]
;内存循环BUFB
PUSH CX
PUSH SI
MOV CX,30
MOV SI,OFFSET BUFB
B:
MOV BL,[SI]
CMP AL,BL
JE DONE
INC SI
LOOP B
;复制到BUFC中
MOV [DI],AL
INC DI
DONE:
POP SI
POP CX
INC SI
LOOP A
MOV AH,4CH
INT 21H
CODE ENDS
END START
已知数组A包含20个互不相等的字型整数,数组B包含30个互不相等的字型整数,试编制一程序把既在A中又在B中出现的数存放于数组C中。
和上面的一样,只不过条件换了一下
DATA SEGMENT
BUFA DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
BUFB DB 11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
BUFC DB 50 DUP('$')
DATA ENDS
STACKS SEGMENT STACK
DW 100 DUP(0)
STACKS ENDS
CODE SEGMENT
ASSUME DS:DATA,CS:CODE,SS:STACKS
START:
MOV AX,DATA
MOV DS,AX
MOV DX,STACKS
MOV SS,DX
;外层循环BUFA
MOV CX,20
MOV SI,OFFSET BUFA
MOV DI,OFFSET BUFC
A:
MOV AL,[SI]
;内存循环BUFB
PUSH CX
PUSH SI
MOV CX,30
MOV SI,OFFSET BUFB
B:
MOV BL,[SI]
CMP AL,BL
JE COPYTOC
INC SI
LOOP B
JMP DONE
COPYTOC:
;复制到BUFC中
MOV [DI],AL
INC DI
DONE:
POP SI
POP CX
INC SI
LOOP A
MOV AH,4CH
INT 21H
CODE ENDS
END START
- 判断一个不超过65535的整数是否为质数
这个用c写也同样非常的基础
算法很简单,把所有非1和自身的数都除一遍,能整除就说明不是质数
DATA SEGMENT BUF DW 13 YES DB 'yes','$' NO DB 'no','$' FLAG DB 00H DATA ENDS STACKS SEGMENT STACK DW 100 DUP(0) STACKS ENDS CODE SEGMENT ASSUME DS:DATA,CS:CODE,SS:STACKS START: MOV AX,DATA MOV DS,AX ;判断 CALL JUDGE ;输出 CALL OUTPUT MOV AH,4CH INT 21H JUDGE PROC PUSH AX PUSH CX PUSH DX PUSH SI MOV SI,OFFSET FLAG MOV DX,0000H MOV AX,BUF MOV CX,AX DEC CX A: DIV CX CMP DX,0 JE NOTPRIME MOV AX,BUF MOV DL,0 DEC CX CMP CX,01H JNE A MOV AL,01H MOV [SI],AL JMP DONE NOTPRIME: MOV AL,00H MOV [SI],AL DONE: POP SI POP DX POP CX POP AX RET JUDGE ENDP OUTPUT PROC PUSH AX PUSH SI PUSH DX MOV SI,OFFSET FLAG MOV AL,[SI] CMP AL,0 JE OUTPUTNO MOV DX,OFFSET YES MOV AH,09H INT 21H JMP FINISH OUTPUTNO: MOV DX,OFFSET NO MOV AH,09H INT 21H FINISH: POP DX POP SI POP AX RET OUTPUT ENDP CODE ENDS END START