目录
一、实验目的
二、实验内容
三.实验步骤以及结果
1、阅读monthtab.asm 程序,要求写出该程序功能,并在实验报告中画出其程序流程图
2.编写一段程序,要求在长度为20的数组(无符号数)中,找出大于42H的无符号数的个数并存入字节单元UP中,找出小于42H的无符号数的个数存入字节单元DOWN中。并利用int 21h dos功能输出 UP 和DOWN 的值
3. 给定一个年份,判断其是否是闰年,是闰年请输出“是”,否者输“否”
总结
一、实验目的
1、了解汇编语言程序条件分支和循环设计结构
2、熟悉各种跳转指令的使用
二、实验内容
- 阅读monthtab.asm 程序,要求写出该程序功能,并在实验报告中画出其程序流程图
- 编写一段程序,要求在长度为20的数组(无符号数)中,找出大于42H的无符号数的个数并存入字节单元UP中,找出小于42H的无符号数的个数存入字节单元DOWN中。并利用int 21h dos功能输出 UP 和DOWN 的值
数组数据: 18H,42H,36H,43H,42H,19H,50H,51H,8FH,42H,
34H,5AH,0BCH,3AH,0BFH, 0FFH,03H,3BH,42H, 012H
3. 给定一个年份,判断其是否是闰年,是闰年请输出“是”,否者输“否”
三.实验步骤以及结果
1、阅读monthtab.asm 程序,要求写出该程序功能,并在实验报告中画出其程序流程图
2.编写一段程序,要求在长度为20的数组(无符号数)中,找出大于42H的无符号数的个数并存入字节单元UP中,找出小于42H的无符号数的个数存入字节单元DOWN中。并利用int 21h dos功能输出 UP 和DOWN 的值
数组数据: 18H,42H,36H,43H,42H,19H,50H,51H,8FH,42H,
34H,5AH,0BCH,3AH,0BFH, 0FFH,03H,3BH,42H, 012H
代码如下:
stack segment stackstack endsdataseg segmentarray DW 18H, 42H, 36H, 43H, 42H, 19H, 50H, 51H, 8FH, 42H DW 34H, 5AH, 0BCH, 3AH, 0BFH, 0FFH, 03H, 3BH, 42H, 012H UP DB ? DOWN DB ? msg1 DB 'UP: $' msg2 DB 'DOWN: $' newline DB 13, 10, '$'
dataseg endscode segment
assume cs:code, ds:dataseg, ss:stackstart: mov ax, dataseg mov ds, ax xor cx, cx ; cx = 0, 初始化计数器 xor bx, bx ; bx = 0, 用于数组索引 xor al, al ; al = 0, 用于存储比较结果 ; 遍历数组,比较每个元素与42H mov si, offset array mov cl, 20 ; 数组长度为20 check_loop: cmp cx, cl ; 检查是否检查完所有元素 jge end_check mov ax, [si + bx] ; 加载当前元素到ax and ax, 0FFH ; 保留低8位,因为是无符号数 cmp ax, 42H ; 与42H比较 ja greater_than ; 如果大于42H,跳转 jb less_than ; 如果小于42H,跳转 ; 如果等于42H,不做任何事情,继续下一个元素 inc bx inc cx jmp check_loop greater_than: inc byte ptr [UP] ; 大于42H的计数器加1 jmp continue_loop less_than: inc byte ptr [DOWN] ; 小于42H的计数器加1 continue_loop: inc bx inc cx jmp check_loop end_check: ; 使用DOS中断21h输出UP和DOWN的值 mov ah, 09h ; DOS功能号:显示字符串 lea dx, msg1 ; 加载消息地址到DX int 21h mov ah, 02h ; DOS功能号:显示字符 mov dl, [UP] ; 加载UP值到DL add dl, 30h ; 转换为ASCII码 int 21h mov ah, 09h ; DOS功能号:显示字符串 lea dx, newline ; 加载换行符地址到DX int 21h mov ah, 09h ; DOS功能号:显示字符串 lea dx, msg2 ; 加载消息地址到DX int 21h mov ah, 02h ; DOS功能号:显示字符 mov dl, [DOWN] ; 加载DOWN值到DL add dl, 30h ; 转换为ASCII码 int 21h ; 程序结束 mov ax, 4C00h ; DOS功能号:退出程序 int 21h
code endsend start
3. 给定一个年份,判断其是否是闰年,是闰年请输出“是”,否者输“否”
实验代码:
data segment ;定义数据段infon db 0dh,0ah,'Please input a year: $' ;infon ,双字节,回车换行,内容Y db 0dh,0ah,'This is a leap year! $' ;y ,双字节,回车换行,内容N db 0dh,0ah,'This is not a leap year! $' ;n ,双字节,回车换行,内容($是结束符)w dw 0 ;w为双字类型buf db 8 ;开辟8个双字节类型的缓冲区,未赋值db ? db 8 dup(?)
data endsstack segment stackdb 200 dup(0) ;开辟200个双字节类型的存储空间。(保护现场用到)
stack endscode segmentassume ds:data,ss:stack,cs:codestart:mov ax,data ;寄存器间的数据交换,把data给了数据段mov ds,axlea dx,infon ;在屏幕上显示提示信息mov ah,9int 21hlea dx,buf ;从键盘输入年份字符串mov ah,10int 21hmov cl, [buf+1] ;把buf+1地址指向的内容给cl,buf长度lea di,buf+2 ;把buf+2的地址给di,buf偏移地址call datacate ;调用函数datacate,传递参数call ifyears ;调用函数ifyears,由参数判断是否为闰年jc a1 ;若产生进位就跳到a1处lea dx,n ;dx加载n的地址'This is not a leap year!'mov ah,9 ;显示dx内的内容int 21hjmp exit ;跳到exita1: lea dx,y ;dx加载y的地址'This is a leap year!'mov ah,9int 21hexit: mov ah,4ch ;结束本程序,返回 DOS 操作系统int 21h;实现将字符串的闰年转换为数字存储在ax中
datacate proc near; ;段内调用,子函数1push cx; ;保护现场 dec cx lea si,buf+2 ;把buf+2的地址给sitt1: inc si ;移动到字符串指定位置loop tt1 ;循环函数是个递增函数, loop指令的格式是:loop标号,cpu执行loop指令的时候,要进行两步操作;1:(cx)=(cx)-1 ;2:判断cx中的值,不为零则转至标号处执行,如果为零,则向下执行;lea si,cx[di]pop cx ;恢复现场mov dh,30h mov bl,10 ;乘数设置为10mov ax,1 l1: push ax ;保护现场sub byte ptr [si],dh ;没有寄存器参与的内存单元访问指令(DMA),si-dh保存在si中mul byte ptr [si] ;没有寄存器参与的内存单元访问指令(DMA),ax*si,结果放在eax中,这里的寄存器si是16位,被乘数在ax中也是16位。;MUL r/m(寄存器或者内存) ;mul是字内乘法,把si对应的地址内一个字的长度赋给;如果参数是 r8/m8, 将把 AL 做乘数, 结果放在 AX;如果参数是 r16/m16, 将把 AX 做乘数, 结果放在 EAX;如果参数是 r32/m32, 将把 EAX 做乘数, 结果放在 EDX:EAXadd w,ax ;w+ax,结果存入w,存入的是数字pop ax ;恢复现场mul bl ;bl*al,结果存放在ax中dec si ;si中的内容减一loop l1 ;l1循环,cx判断次数retdatacate endp;实现ax中年份的判断ifyears proc near ;段内调用,子函数2push bx ;保护现场(保护谁,就用到谁)push cxpush dxmov ax,w ;把w值赋给cx,w值为mov cx,ax ;把ax值赋给cxmov dx,0 mov bx,4 ;ax/4div bx ;ax/bx,结果在ax中,余数在dx中;如果除数是8位,那么除法的结果AL保存商,AH保存余数,;如果除数是16位,那么除法的结果 AX保存商,DX保存余数。cmp dx,0 ;比较余数和0,结果存入cf标志位(进位标志位)jnz lab1 ;如果非0,跳转到lab1处mov ax,cx mov bx,100 ;ax/100div bx cmp dx,0 ;比较余数和0,结果存入cf标志位(进位标志位)jnz lab2 ;如果非0,跳到lab2mov ax,cx mov bx,400 ;ax/400div bx cmp dx,0 ;比较余数和0,结果存入cf标志位(进位标志位)jz lab2 ;cf=0跳到lab2lab1: clc ;清除cf标志位,设置cf=0jmp lab3 ;跳到lab3lab2: stc ;cf置1lab3: pop dx ;恢复现场pop cx pop bxretifyears endp
code endsend start
测试结果如下:
2100是错的,其余三种情况是正确的。
总结
学到后期,摆烂太多,发现自己稍难一点的汇编代码都不会敲,只能从网上复制粘贴。这算复制粘贴的比较靠谱的代码。