北理的汇编期末题其实也没太大难度,很多三星题都是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