分享SCAU汇编实验代码
实验一
计算(859FH*3)+8765H的值 ,并把结果存在存储器数据段偏移量3578H开始的位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 DATAS SEGMENT ;此处输入数据段代码 DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ; 题目: ; 计算 (859FH * 3) + 8765H的值 ; 结果存在存储器数据段偏移量3578H开始的位置 ; 此处输入代码段代码 MOV AX,859FH MOV BX,3 MUL BX ADD AX,8765H ADC DX,0 MOV DS:[3578H],AX MOV DS:[357AH],DX ; 此处输入代码段代码 MOV AH,4CH INT 21H CODES ENDS END START
实验二
判断AX中的年份(无符号整数)是否闰年,是则将0001传送到BX,否则将BX清零(分别用数据1900、2008、1999、2000做测试)
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 DATAS SEGMENT ;此处输入数据段代码 DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ; 题目: ; 判断AX中的年份(无符号整数)是否闰年? ; 是则将0001传送到BX,否则将BX清零 ; (分别用数据1900、2008、1999、2000做测试) ; 此处输入代码段代码 MOV AX,1900 ; 测试年份 MOV DX,0 MOV CX,AX ; 保存年份 MOV BX,400 DIV BX TEST DX,DX JZ L2 ; 整除400 直接跳转L2 MOV AX,CX MOV DX,0 MOV BX,4 DIV BX TEST DX,DX JNZ L1 ; 无法整除4 直接跳转L1 MOV AX,CX MOV BX,100 DIV BX TEST DX,DX JZ L1 ; 整除4 & 整除100 跳转L2 JNZ L2 ; 无法整除100 跳转L1 L1: MOV BX,0 MOV AH,4CH INT 21H L2: MOV BX,0001H ; 此处输入代码段代码 MOV AH,4CH INT 21H CODES ENDS END START
实验三
将用户输入的四位(测试数据固定四位)十六进制数变成二进制形式输出(所有字母大写,用户输入非法字符则结束)例如用户输入50F0则输出0101000011110000测试数据:50F0,123A
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 DATAS SEGMENT ;此处输入数据段代码 DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ; 题目: ; 将用户输入的四位(测试数据固定四位) ; 十六进制数变成二进制形式输出 ; 所有字母大写,用户输入非法字符则结束 ; 例如用户输入50F0则输出0101000011110000 ; 此处输入代码段代码 MOV BX,0 MOV CH,4 ; 循环次数 INPUT: MOV AH,01H ; 输入一个字符,ASCII码在AL中 INT 21H CMP AX,0130H ; 判断是否非法,AX < 0 JL EXIT CMP AX,0139H ; 判断是否数字 JLE L1 ; 是数字,跳转L1 CMP AX,0141H ; 判断是否非法,9 < AX < A JL EXIT CMP AX,015AH ; 判断是否非法,AX > Z JNLE EXIT SUB AL,07H ; 要把A当成数字10,减去A与9中间的差值 L1: SUB AL,30H ; 把ASCII码转换为数字 MOV CL,4 SHL BX,CL ; BX每次左移4位 ADD BL,AL ; 将数字加到BX中 DEC CH ; 循环次数减一 CMP CH,0 ; 判断循环是否结束 JNZ INPUT ; 循环未结束,跳回 ;处理结束,输出换行符 MOV DL,10 MOV AH,02H INT 21H MOV CH,16 ; 循环计数器,用来输出16位二进制数 L2: SHL BX,1 ; BX左移1位,暂存到CF中 JC SET1 ; 若CF为1,则跳转到SET1标签 MOV DL,30H ; 若CF为0,则DL存'0' JMP PRINT ; 跳转到PRINT标签,输出DL中的字符 SET1: MOV DL,31H ; CF为1,则DL存'1' PRINT: MOV AH,02H ; 输出字符 INT 21H DEC CH ; 循环次数减一 CMP CH,0 ; 判断循环是否结束 JNZ L2 ; 循环未结束,跳回 EXIT: MOV AH,4CH INT 21H ;此处输入代码段代码 CODES ENDS END START
统计长度为N的字数组ARRAY中有多少种不同数值,例如数组{1,1,3,5,5}中有三种不同数值。将结果存放进BX测试数据:{1,1,3,5,5}{4,2,5,2,5,4,6,7,4,6,9,11,15,9}
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 DATAS SEGMENT ;此处输入数据段代码 FRONT LABEL WORD ARRAY DW 4, 2, 5, 2, 5, 4, 6, 7, 4, 6, 9, 11, 15, 9 BACK LABEL WORD DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ; 题目: ; 编写程序,统计长度为N的字数组ARRAY中有多少种不同数值 ; 例如: 数组{1,1,3,5,5}中有三种不同数值,将结果存放进BX ; 测试数据:{1,1,3,5,5} ; {4,2,5,2,5,4,6,7,4,6,9,11,15,9} ; 此处输入代码段代码 MOV BX,0 ; 初始化计数器 LEA DX,FRONT LEA CX,BACK SUB CX,DX ; CX记录数组长度 MOV SI,0 L1: ; 第一层循环 MOV DX,ARRAY[SI] ; DX暂存a[i] MOV DI,0 L2: CMP DI,SI ; 表示i==j JZ ANS ; 跳转ANS MOV AX,ARRAY[DI] ; AX暂存a[j] CMP AX,DX ; 比较a[i],a[j] JE NEXTL2 ; 表示a[i]==a[j],跳转NEXTL2 ADD DI,2 ; j++ JMP L2 ; 继续内层循环 ANS: INC BX NEXTL2: ADD SI,2 CMP SI,CX JB L1 ; 此处输入代码段代码 MOV AH,4CH INT 21H CODES ENDS END START
实验四
若数据段定义
1 2 3 4 data segment array1 dw 11,22,3BH,4,35,100,12,27,78,24 sum dw ? data ends
求数组array1中所有 偶数 的和,存放在sum中。测试时除了以上数据外,还需测试以下array1array1 dw 5,128,34,77,22,301,89,64,50,66
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 DATAS SEGMENT array1 dw 11,22,3BH,4,35,100,12,27,78,24 sum dw ? DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ; 题目: ; 若数据段定义 ; data segment ; array1 dw 11,22,3BH,4,35,100,12,27,78,24 ; sum dw ? ; data ends ; 求数组array1中所有 偶数 的和,存放在sum中。 ; 测试时除了以上数据外,还需测试 ; array1 ; array1 dw 5,128,34,77,22,301,89,64,50,66 ;此处输入代码段代码 MOV SI,0 MOV CX,10 ; 循环次数 MOV DX,0 ; 初始化累加器 L1: MOV AX,array1[SI] TEST AX,1 ; 测试奇偶性 JNZ ODD ; 奇数跳转 ADD DX,AX ; 偶数累加 ODD: ADD SI,2 ; 指针加2 LOOP L1 ; cx≠0,循环继续 MOV sum,DX ; 循环结束,结果存在sum中 ;此处输入代码段代码 MOV AH,4CH INT 21H CODES ENDS END START
将AX中数据的二进制形式倒置,并以二进制形式输出。例如0000000011110001,倒置后为1000111100000000(测试数据为1234H,5678H,00FFH,无需做输入,直接在程序中修改测试数据,需要做输出)
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 DATAS SEGMENT ; 此处输入数据段代码 DATAS ENDS STACKS SEGMENT ; 此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ; 题目: ; 将AX中数据的二进制形式倒置,并以二进制形式输出。 ; 例如0000000011110001,倒置后为1000111100000000 ; 测试数据为1234H,5678H,00FFH ; 无需做输入,直接在程序中修改测试数据,需要做输出 ; 此处输入代码段代码 MOV AX,1234H MOV CX,2 ; 除数2 MOV BX,16 ; 计数器,记录未输出位数 L1: XOR DX,DX ; 清空DX DIV CX ; 除以2,相当于取出末位 CALL PRINT ; 调用打印函数 CMP AX,0 ; 检查是否为0 JNZ L1 ; 不为0,继续循环 MOV CX,BX ; 剩余位数皆为0,存到CX作循环输出 L2: MOV DX,0 ; DX置0 ADD DX,30H ; 转换为ASCII码 MOV AH,2 ; 调用21号中断的2号功能,输出DX中字符 INT 21H LOOP L2 ; CX≠0继续循环 MOV AH,4CH ; =退出 INT 21H PRINT: PUSH AX ; 压栈保存AX,DX PUSH DX ADD DX,30H ; 转换为ASCII码 MOV AH, 2 ; 调用21号中断的2号功能,输出DX中字符 INT 21H POP DX ; 出栈恢复AX,DX POP AX DEC BX ; 已输出1位,计数器减1 RET ; 此处输入代码段代码 CODES ENDS END START
用户输入四位十六进制数(固定四个字符,如“A123” ”0035”“123f”, 字母可能大写或小写,输入非法字符则退出),在屏幕输出其十进制形式。
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 DATAS SEGMENT bin dw 10 dup(?) ;存放二进制结果 buf db 5 dup(?) ;存放十进制数 各个数位上的数值 如100,存放为 1,0,0 msg1 db 'please input a hex number',13,10,'$' msg2 db 'the dec number:',13,10,'$' crlf db 13,10,'$' ;回车换行 DATAS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS START: MOV AX,DATAS MOV DS,AX mov bx,0 ;初始化bx input: mov ah,1 ;输入一个字符 int 21h sub al,30h ;把al中的ascii码转换成数值 jl init cmp al,10 ;输入的数在0-9之间跳转 jl toBin ADD AL,30H CMP AL,41H JL EXIT CMP AL,46H JNLE L1 ADD AL,20H L1: SUB AL,30H sub al,27h ;再转换为a-f cmp al,0ah ;输入的字符比a小 jl init ;结束输入 cmp al,10h ;输入的字符比f大 jge init ;结束输入 toBin: ;转换为二进制,把输入组合成意义上的数值 mov cl,4 shl bx,cl ;bx左移4位 mov ah,0 add bx,ax ;把输入后并从ascii码转换来的值与bx相加 mov bin,bx ;转换成二进制数后存到内存bin jmp input ;继续输入 init: ;初始化,准备转换 mov ax,bin mov bx,10 mov si,4 ;循环四次,最大到万位 toDec: ;转为各个数位上的数值,如100转换为1,0,0 百位为1... mov dx,0 div bx ;除10法得到各个位上的数值 mov [buf+si],dl ;余数为该位上的值,第一次循环为个位,第二次为十位...;存到内存中 dec si cmp ax,0 ;商是否为0,为0算法结束 ja toDec output: ;输出内存中存放的各个数位上的数值 inc si mov dl,[buf+si] add dl,30h ;转为ascii mov ah,2 int 21h cmp si,4 jb output mov ah,1 int 21h MOV AH,4CH INT 21H EXIT: MOV AH,4CH INT 21H CODES ENDS END START
实验五
在屏幕上输出2-100之间的所有素数(源程序里要求用到子程序判断是否素数,以及用子程序输出十进制整数,要有计算过程,不可以直接抄结果输出)
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 DATAS SEGMENT ;此处输入数据段代码 DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: ; 问题 ; 在屏幕上输出2-100之间的所有素数 ; 源程序里要求用到子程序判断是否素数,以及用子程序输出十进制整数 ;此处输入代码段代码 MAIN PROC FAR MOV AX,DATAS MOV DS,AX MOV CX,1 ; 计数器,1 < CX <100 L1: INC CX ; i++ MOV AX,CX ; 将CX存到AX中 PUSH CX ; CX压栈 CALL IS_PRIME ; 判断是否素数 POP CX ; CX出栈 CMP BX,0 ; 判断素数标志位 JZ L2 ; 非素数,不打印 CALL PRINT ; 素数,打印 L2: CMP CX,100 ; 判断CX < 100 JL L1 ; < 继续循环 MOV AH,4CH ; 退出 INT 21H MAIN ENDP IS_PRIME PROC NEAR PUSH AX ; AX压栈 MOV BX,1 ; 标志:是否素数 MOV CX,2 ; i 因子 L3: POP AX ; AX出栈 PUSH AX ; AX进栈 CMP CX,AX ; 判断CX是否 < AX JE PRIME ; CX == AX MOV DX,0 ; 清空DX DIV CX ; 除因子 CMP DX,0 ; 判断能否整除 JE NOT_PRIME ; 能整除不是素数 INC CX ; 因子++ JMP L3 ; 继续循环 NOT_PRIME: MOV BX,0 ; 不是素数,置标志为0 PRIME: POP AX RET ; 返回 IS_PRIME ENDP PRINT PROC NEAR MOV BL,10 DIV BL ; 除10 MOV BX,AX ; BX暂存AX内容 MOV AH,02H MOV DL,BL ; 打印 商(即十位数) ADD DL,30H ; +'0' INT 21H MOV DL,BH ; 打印 余数(即个位数) ADD DL,30H INT 21H MOV DL,' ' ; 打印空格 INT 21H RET PRINT ENDP ;此处输入代码段代码 CODES ENDS END START
编写程序,将数据段里的某数组在原位置逆序(例如ARRAY数组{1,2,3}变为{3,2,1},但首地址依然是ARRAY),要求用子程序实现逆序操作。子程序要求有一定通用性,能够处理不同数组。
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 DATAS SEGMENT ARY DW 1,2,3 ARY_SIZE EQU ($-ARY)/2 ; 数组长度 DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ; 问题 ; 编写程序,将数据段里的某数组在原位置逆序 ; 例如ARRAY数组{1,2,3}变为{3,2,1},但首地址依然是ARRAY ; 要求用子程序实现逆序操作。 ;此处输入代码段代码 MOV AX,OFFSET ARY PUSH AX MOV AX,OFFSET ARY_SIZE PUSH AX CALL REVERSE ; 调用逆序子程序 MOV AH,4CH ; 退出 INT 21H REVERSE PROC NEAR PUSH BP MOV BP,SP PUSH AX PUSH CX PUSH SI PUSH DI LEA AX,ARY ; 加载ary首地址到ax MOV SI,AX MOV CX,ARY_SIZE ; cx=ary[size] MOV DI,SI MOV AX,CX MOV BL,2 MUL BL ADD DI,AX ;数组的尾地址的下一个地址 SUB DI,2 ; 现在指向数组的尾地址 L1: CMP CX,0 JLE OVER MOV AL,[SI] XCHG AL,[DI] MOV [SI],AL INC SI DEC DI LOOP L1 OVER: POP DI POP SI POP CX POP AX POP BP RET 6 REVERSE ENDP CODES ENDS END START
编写程序,寻找一个数组里的最大值。其中查找最大值的过程使用子程序,参数传递使用堆栈。
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 DATAS SEGMENT ; 定义数据段,存储数据 ARRAY DW 2,3,4,10 BACK LABEL WORD ; 定义一个字大小的标签 DATAS ENDS STACKS SEGMENT ; 定义堆栈段 STACKS ENDS CODES SEGMENT ; 定义代码段 ASSUME CS:CODES,DS:DATAS,SS:STACKS ; 定义段寄存器 START: MAIN PROC FAR MOV AX,DATAS MOV DS,AX MOV AX, OFFSET ARRAY ; 将数组ARRAY的偏移地址加载到AX中(第一个元素的地址) PUSH AX ; 将数组ARRAY的偏移地址压入堆栈(第一个元素的地址) MOV AX, OFFSET BACK ; 将数组BACK的偏移地址加载到AX中(最后一个元素的地址) PUSH AX ; 将数组BACK的偏移地址压入堆栈(最后一个元素的地址) CALL FINDMAX ; 调用名为FINDMAX的子程序 MOV AH,4CH INT 21H RET MAIN ENDP ; 用于查找数组中的最大值 FINDMAX PROC NEAR MOV BP,SP ; 将栈指针加载到BP寄存器中 MOV SI,[BP+4] ; 将堆栈中第一个参数的偏移地址加载到SI中(数组的第一个元素的地址) MOV DI,[BP+2] ; 将堆栈中第二个参数的偏移地址加载到DI中(数组的最后一个元素的地址) MOV AX,[SI] ; 将AX加载为数组的第一个元素的值 ADD SI,2 L1: CMP SI,DI ; 比较SI和DI,检查是否已经遍历完整个数组 JNB OVER ; 如果SI大于等于DI(已经到达数组末尾),则跳转到OVER CMP AX,[SI] ; 比较AX(当前最大值)和[SI](当前元素的值) JNB NEXT ; 如果AX大于等于[SI],则跳转到NEXT MOV AX,[SI] ; 更新AX为[SI]的值(新的最大值) NEXT: ADD SI,2 ; 移动到数组的下一个元素 JMP L1 ; 跳回L1,继续遍历数组 OVER: RET 4 ; 从子程序返回,从堆栈中弹出4个字节 FINDMAX ENDP CODES ENDS END START
实验六
在屏幕上输出字符串“welcome to asm”,要求逐个字符输出,每隔约0.5秒左右(可以有0.05秒内的误差)输出一个字符。
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 DATAS SEGMENT ;此处输入数据段代码 STRING DB 'welcome to asm',0dh,0ah,'$' ; 0DH,0AH 回车,换行 DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS MS1 = 325 ; 1ms延时 START: MOV AX,DATAS MOV DS,AX ; 问题 ; 在屏幕上输出字符串“welcome to asm” ; 要求逐个字符输出,每隔约0.5秒左右(可以有0.05秒内的误差)输出一个字符 ;此处输入代码段代码 MOV CX,14 ; 字符串长度 MOV BX,0 ; 计数器BX LEA DX,STRING ; STRING的地址存在DX CALL PRINT ; 打印字符串 MOV AH,4CH INT 21H PRINT PROC L1: MOV DL,[STRING+BX] ; 字符加载到DL中 MOV AH,02H ; 输出 INT 21H INC BX ; 计数器+1 PUSH CX PUSH DX MOV AL,1 ; 设置延时1次 CALL TIME ; 调用延时程序 POP DX POP CX LOOP L1 RET PRINT ENDP ;延时0.5s子程序 TIME PROC S0: MOV CX,500 ; 内循环延时约1ms,外循环500次,则内循环一轮为0.5s S1: MOV DX,MS1 ; 延时次数计数 S2: DEC DX ; 第一层循环 1ms JNZ S2 DEC CX ; 第二层循环 0.5s JNZ S1 DEC AL JNZ S0 RET TIME ENDP CODES ENDS END START
实现秒表,即从0秒开始进行计时,随着时间经过变更显示的秒数(例如经过10秒则显示10,最多100秒。可以有0.1秒以内的误差。)
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 DATAS SEGMENT ;此处输入数据段代码 COUNTER DB 0 COUNTER1 DB 0 COUNTER2 DB 0 TIME EQU 60000 ; 延迟计数器的值,根据实际需要调整 DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ; 问题 ; 实现秒表,即从0秒开始进行计时,随着时间经过变更显示的秒数 ; 例如经过10秒则显示10,最多100秒。可以有0.1秒以内的误差。 ; 提示:变更已显示的内容可以清屏后重新显示,清屏可以用 ; MOV AX,3 ; INT 10H ;此处输入代码段代码 MOV AX, 3 ; 清屏 INT 10H MOV BX, 0 L2: ; 百位 MOV DL, [COUNTER2] ADD DL, '0' ; 转换ASCII码 MOV AH, 02H INT 21H ; 显示字符 L1: ;十位 MOV DL, [COUNTER1] ADD DL, '0' ; 转换ASCII码 MOV AH, 02H INT 21H ; 显示字符 L0: ; 个位 MOV DL, [COUNTER] ; 计数器加载到DL ADD DL, '0' ; 转换ASCII码 MOV AH, 02H INT 21H ; 显示字符 MOV DI, 30 ; 延迟一段时间 SET_CX: MOV CX, TIME ; 初始化延迟计数器 DELAY_LOOP: DEC CX ; 计数器减1 JNZ DELAY_LOOP ; 如果计数器不为0,则继续循环延迟 DEC DI JNZ SET_CX INC [COUNTER] MOV AX, 3 ; 清屏 INT 10H CMP [COUNTER2], 1 ;检查是否超过100秒 JE RESET_C CMP [counter], 10 ; 检查计时器0是否超过10秒 JNE L2 ; 如果未超过10秒 CMP [counter], 10 JE C_1 C_1: ;十位进位 INC [COUNTER1] MOV [COUNTER], 0 CMP [COUNTER1], 10 JE C_2 JMP L2 C_2: ;百位进位 INC [COUNTER2] MOV [COUNTER1], 0 JMP L2 RESET_C: ;重置时间为000 MOV [COUNTER], 0 MOV [COUNTER1], 0 MOV [COUNTER2], 0 JMP L2 MOV AH,4CH INT 21H CODES ENDS END START
实验七
将用户输入的无符号十进制数(不超过4位)变成十六进制的形式输出测试数据:1234,5,7008,66
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 DATA SEGMENT STRING DB 0DH,0AH,"OVERFLOW!",'$' DATA ENDS STACK SEGMENT STACK DW 100 DUP (?) TOP LABEL WORD STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK MAIN PROC FAR MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX LEA SP,TOP MOV BX,0 MOV CX,0 ;统计合法的数字字符个数 MOV SI,10 MOV BP,0 ;符号位默认为0(正数) MOV AH,7 ;输入第一个字符 INT 21H CMP AL,0DH ;输入回车,退出 JE EXIT L1: CMP AL,'+' JNE L3 ;不是正号,跳转到L3继续判断 MOV BP,0 ;输入正号,更改符号位 MOV DL,AL ;显示正号 MOV AH,2 INT 21H JMP L2 ;跳转到L2继续输入数字字符 L2: MOV AH,7 INT 21H CMP AL,0DH ;输入回车,跳转到以16进制显示BX JE PRINT L3: CMP AL,30H ;小于30H,继续输入 JB L2 CMP AL,39H ;大于39H,继续输入 JA L2 MOV DL,AL ;显示合法的数字字符 MOV AH,2 INT 21H INC CX ;合法的数字字符+1 AND DX,0FH ;屏蔽DX高12位 MOV AX,DX XCHG AX,BX ;交换AX和BX MUL SI ;AX*10 ;数字部分以无符号数输入 ;限制数字部分的输入范围0-65535 JC OVERFLOW ADD BX,AX JC OVERFLOW JMP L2 ;无溢出,跳转到L2继续输入数字字符 PRINT: CMP CX,0 ;判断合法的数字字符个数,CX为0退出 JE EXIT ;接下来判断有符号数的溢出 CMP BP,1 JE NEGATIVE ;判断负数的溢出 CMP BP,0 JE POSITIVE ;判断正数的溢出 NEGATIVE: NEG BX ;BX是负数,求补 ADD BX,0 ;这条指令会改变PSW,接下来判断符号位 JNS OVERFLOW ;符号位是0,溢出 JMP L4 ;跳转到L4以16进制显示BX POSITIVE: ADD BX,0 ;BX是正数 JS OVERFLOW ;符号位是1,溢出 L4: MOV CX,4 MOV DL,0DH MOV AH,2 INT 21H MOV DL,0AH MOV AH,2 INT 21H L5: PUSH CX MOV CL,4 ROL BX,CL MOV DL,BL AND DL,0FH CMP DL,9 JA L6 ADD DL,30H JMP L7 L6: ADD DL,37H L7: MOV AH,2 INT 21H POP CX LOOP L5 CMP CX,0 JE EXIT OVERFLOW: LEA DX,STRING MOV AH,9 INT 21H EXIT: MOV AH,4CH INT 21H MAIN ENDP CODE ENDS END MAIN
创建文件abc.txt,并由用户输入不超过128个字符保存。创建文件def.txt,将abc.txt中的内容倒置保存(例如,”abcdef”变为“fedcba”,文件位置自定)
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 DATAS SEGMENT ;此处输入数据段代码 FILE1 DB 'abc.txt',0 HANDLE1 DW ? FILE2 DB 'def.txt',0 HANDLE2 DW ? BUFFER DB 256 DUP(0) DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX MOV AH,3CH ;INT 21H的3CH功能 LEA DX,FILE1 ;DX=ASCIIZ串的首地址 MOV CX,0 ;CX=0,普通文件 INT 21H ;新建文件 JC ERROR ;新建不成功,转ERROR MOV HANDLE1,AX ;成功,保存文件句柄 READ0: ;读入字符 MOV AH,1 INT 21H CMP AL,0Dh JZ L1 ;若是回车则结束 MOV AH,40H MOV BUFFER,AL LEA DX,BUFFER MOV BX,HANDLE1 MOV CX,1 INT 21H JC ERROR ;写入错误 JMP READ0 L1: ;将FILE1的内容放到BUFFER中 MOV BX,AX MOV CX,255 MOV DX,OFFSET BUFFER MOV AH,3FH INT 21H JC ERROR ;将BUFFER的内容倒置 MOV SI,0 MOV DI,AX DEC DI ;倒置操作 LOP1: CMP SI,DI JAE NEXT MOV BH,BUFFER[SI] MOV BL,BUFFER[DI] MOV BUFFER[SI],BL MOV BUFFER[DI],BH INC SI DEC DI JMP LOP1 NEXT: ;创建并打开FILE2文件 MOV DX,OFFSET FILE2 MOV CX,0 MOV AH,3CH INT 21H JC ERROR MOV HANDLE2,AX ;将BUFFER的内容写入FILE2中 MOV BX,HANDLE2 MOV DX,OFFSET BUFFER MOV CX,255 MOV AH,40H INT 21H OVER: ;关闭FILE1文件 MOV BX,HANDLE1 MOV AH,3EH INT 21H ;关闭FILE2文件 MOV BX,HANDLE2 MOV AH,3EH INT 21H ERROR: MOV AH,4CH INT 21H EXIT0: ;关闭文件 MOV AH,3EH MOV BX,HANDLE1 INT 21H MOV AH,4CH INT 21H CODES ENDS END START
判断数据段中定义的两个数a和b是否互素(ab均为小于10000的正整数),要求编写子程序完成,采用堆栈传递参数。
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 DATA SEGMENT a DW ? b DW ? g DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX, DATA MOV DS, AX ; 假设a和b的值已经通过某种方式赋值,这里直接赋值用于演示 MOV a, 9 MOV b, 3 ; 调用子程序计算最大公约数 MOV AX, a MOV BX, b CALL GCD ; 将计算出的最大公约数存储在gcd变量中 MOV g, CX ; 判断是否互素,即gcd是否为1 MOV CX, 1 CMP g, CX JE MUTUAL_PRIME ; 如果不是互素,可以在这里添加代码处理 JMP END_PROGRAM MUTUAL_PRIME: ; 如果是互素,可以在这里添加代码处理 END_PROGRAM: ; 结束程序 MOV AH, 4CH INT 21H GCD PROC NEAR ; 计算最大公约数的子程序 MOV CX, BX ; 将b的初始值传给CX,作为辗转相除的初始除数 MOV BX, 0 GCD_LOOP: MOV DX, 0 ; DX用于存放余数 ; AX除以CX,商在AX中,余数在DX中 DIV CX CMP DX, 0 ; 检查余数是否为0 JE GCD_DONE ; 如果余数为0,退出循环 MOV BX, CX ; 将CX的值传给BX,为下一次迭代做准备 MOV CX, DX ; 将余数DX的值传给CX,作为下一次迭代的除数 JMP GCD_LOOP ; 继续循环 GCD_DONE: RET ; 返回主程序 GCD ENDP CODE ENDS END START
实验八
将用户输入的无符号十进制数(不超过4位)变成十六进制的形式输出测试数据:1234,5,7008,66
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 DATAS SEGMENT STR1 DB 0AH,'Input decimal number: ','$' STR2 DB 0AH,'hexadecimal number: ','$' DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ; 问题 ; 将用户输入的无符号十进制数(不超过4位)变成十六进制的形式输出 ; 测试数据:1234,5,7008,66 ;此处输入代码段代码 CALL INPUT ; 调用读取 CALL CONVERT ; 调用转换 MOV AH,4CH ; 程序结束 INT 21H INPUT PROC NEAR LEA DX,STR1 ; 输出提示字符串 MOV AH,09 INT 21H LEAGAL1: MOV AH,01H ; 输入,并在屏幕上显示该字符。 INT 21H CMP AL,'9' ; 比较输入字符合法性 JA EXIT CMP AL,'0' JB EXIT SUB AL,'0' MOV AH,0H MOV DX,AX ; 将新数给 DX MOV AX,BX ; BX 存的是之前的数要去做乘10运算 MOV BX,DX ; 把新数给 BX 在个位 待会儿直接做加法 MOV CX,0AH ; CX的值是10 MUL CX ADD BX,AX JMP LEAGAL1 EXIT: RET INPUT ENDP CONVERT PROC NEAR LEA DX,STR2 MOV AH,09 INT 21H MOV CH,04H MOV CL,04H LOOPC: ROL BX,CL MOV AL,BL AND AL,0fh ADD AL,30H CMP AL,'9' JBE PRINTF ADD AL,07H PRINTF: MOV DL,AL MOV AH,2 INT 21H DEC CH JNE LOOPC RET CONVERT ENDP CODES ENDS END START
编写程序,用户输入一个字符串,统计其中数字字符之和并输出,例如输入”1a2b3c”则输出6(假设和不会超过四位数,输入以回车结束)测试数据:1a2b3c, #1abcD0w623v9
1 2 3 4 5 6 7 8 9 10 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 DATAS SEGMENT ;此处输入数据段代码 DB 0 NOTE DB 'Please enter the sentence: ',0DH,0AH,'$' DATAS ENDS STACKS SEGMENT ;此处输入堆栈段代码 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ; 问题 ; 编写程序,用户输入一个字符串,统计其中数字字符之和并输出 ; 例如输入”1a2b3c”则输出6(假设和不会超过四位数,输入以回车结束) ; 测试数据:1a2b3c, #1abcD0w623v9 ;此处输入代码段代码 MOV AH,09H ;输出提示符 MOV DX,OFFSET NOTE INT 21H CALL COUNT ;调用统计子程序 CALL print MOV AH,4CH INT 21H COUNT PROC NEAR INPUT: MOV AH,01H INT 21H CMP AL,0DH JZ EXIT CMP AL,'0' JL INPUT CMP AL,'9' JA INPUT INC BYTE PTR DS:[0] JMP INPUT EXIT: RET COUNT ENDP print proc near mov al,ds:[0] mov ah,0 mov bx,10 mov cx,0 mov dx,0 legal1: div bx push dx inc cx cwd cmp ax,0 jne legal1 legal2: pop dx add dl,30h mov ah,02h int 21h loop legal2 mov ah,02h mov dl,0dh int 21h ret print endp CODES ENDS END START