昆明理工大学信息工程与自动化学院学生实验报告
( 2014 — 2015 学年 第一学期 )
课程名称:汇编与微机接口 开课实验室:信自楼机房444 2014年12月3日 年级、专业、班 计科122班 学号 201210405204 姓名 实验项目名称 子程序设计 邹华宇 指导教师 成绩 万小容 该同学是否了解实验内容与要求:A.了解□ 教该同学的实验能力: A.强 □ 师该同学的实验是否达到要求: A.达到□ 实验报告是否规范: A.规范□ 评是否有运行结果与分析: A.详细□ 语 是否有总结与体会: A.详细□ B.基本了解□ B.中等 □ B.基本达到□ B.基本规范□ B.一般 □ B.一般 □ C.不了解□ C.差 □ C.未达到□ C.不规范□ C.没有 □ C.没有 □
教师签名: 年 月 日 一、实验目的
1、熟悉并掌握汇编语言的基本指令; 2、熟练地掌握子程序的设计过程;
3、熟悉并掌握BIOS和DOS中断的调用方法;
4、熟悉主程序调用子程序的模块化程序设计思想,即将原始数据通过转换为内存数据再转化为显存数据显示到屏幕上。 二、实验要求
将实验7中的Power idea公司的数据按照图所示的格式在屏幕上显示出来。(用子程序编写代码以十进制方式显示内存中的数据。) 三、实验分析
完成这个实验需要编写以下几个子程序: (1)名称:show_str
功能:在指定的位置,用指定的颜色,显示一个以0结尾的字符串; 参数:(dh)=行号(取值范围0~24),(dl)=列号(取值范围0~79)(cl)=颜色,ds:si指向字符串的首地址。
(2)名称:divdw
功能:进行无溢出的除法操作,被除数为被除数为dword型,除数为word型,结果为word型;
参数:(ax)=dword型数据的低16位,(dx)=dword型数据的高16位,(cx)=除数;
返回:(dx)=结果的高16位,(ax)=结果的低16位,(cx)=余数。 (3)名称:dtoc
功能:将word型数据转变为表示十进制的字符串,字符串以0为结尾符; 参数:(ax)=word型数据,ds:si指向字符串的首地址。 四、实验环境
汇编程序:MASM.EXE,链接程序:LINK.EXE,调试环境:DEBUG.EXE,对操作系统和计算机五特殊要求,如果是WIN7以上操作系统,需要安装DOSBOX虚拟平台。
五、实验过程与结果
assume cs:code,ds:data,es:table ;将代码段的段地址给cs,将数据段的段地址给ds,将table段的段地址给es
table segment ;定义table段
db '1975','1976','1977','1978','1979','1980','1981','1982','1983' db '1984','1985','1986','1987','1988','1989','1990','1991','1992' db '1993','1994','1995'
;表示21年的21个字符串,每个年份占四个字节,共占84字节
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514 dd
345980,590827,803530,1183000,1843000,2795000,3753000,4649000,5937000 ;表示21年公司总收入的21个双字型数据,共占84字节 dw
3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226 dw 11542,14430,15257,17800
;表示21年公司雇员人数的21个字型数据,共占42字节 dw
5,3,42,104,85,210,123,111,105,125,140,136,153,211,199,209,224,239 dw 260,304,333
;表示21年公司雇员人均年收入的21个字型数据,共占42字节 table ends ;table 段结束
data segment ;定义data段
db 32 dup (0) ;预留出32字节的空间
data ends ;data 段结束
code segment ;code段
start:
;将data段、table段的段地址通过中间寄存器赋给ds 、es mov ax, data mov ds, ax mov ax, table mov es, ax
mov bx, 0 ;table段指针清0 mov si, 0 ;data段指针清0 mov di, 0 ;table段指针清0 mov cx, 21 ;循环次数给cx mov dh, 2 ;将行号给dh mov dl, 30 ;列号给dl
s1: push cx ;将寄存器进栈保护,防止将其中数据覆盖 push dx
;取年份,一个年份分两次取
mov ax, es:[bx] ;将table段的值取给ax,一次取两个字节即字符“19”
mov [si], ax ;将ax的值写入内存
mov ax, es:[bx+2] ;取年份的后两个字符,如“75” mov [si+2], ax ;写到内存的相应位置
;取公司总收入
mov ax, es:[bx+84] ;table段中字型数据占84个字节,取年总收入指针加84
mov dx, es:[bx+86]
add si, 6 ;数据段指针加6:总收入加上空格 call dtoc ;调用子程序dtoc mov ax, es:[di+168] ;取公司雇员数 mov dx, 0 ;dx清0
add si, 10 ;数据段指针指向相应位置
call dtoc ;调用子程序,将data段的数据以十进制形式显示
mov ax, es:[di+210] ;取人均年收入:84+84+42=210 mov dx, 0 ;dx清0
add si, 8 ;数据段指针指向相应位置
call dtoc ;调用子程序,将data段的数据以十进制形式显示
mov si, 0 ;指针清0 mov cx, 21 ;循环次数 s2: push cx ;cx进栈保护
mov cl, [si] ;将数据段的字符取给cl
jcxz s4 ;若cx=0,则执行标号s4处的代码 s3: inc si ;指针加1 pop cx ;cx的值出栈
loop s2 ;循环标号s2处的代码,直至cx=0 inc si ;指针加1 mov al, 0 ;将al清0
mov [si], al ;将al的值传到数据段 mov si, 0 ;指针清0 pop dx ;dx的值出栈 mov cl, 2 ;将颜色传给cl call show_str ;调用子程序 add bx, 4 ;指针加4
add di, 2 ;指针加2,指向下一个数据 add dh, 1 ;行号加1,指向下一个数据 pop cx ;cx的值出栈
loop s1 ;循环执行s1处的代码,直至cx=0 mov ax, 4c00h
int 21h s4: mov al, 20h mov [si], al jmp s3
;进栈保护,防止数据在子程序中被覆盖 dtoc:push ax push cx push dx push si push di
mov di, 0 ;保存字符进栈的个数
d1: mov cx, 10 ;将除数10给cx
call divdw ;调用子程序,进行不会溢出的除法运算 add cx, 30h ;cx中存放的是余数,将余数加上30h得到该数字的ASCII码
push cx ;将cx进栈保护 inc di ;字符个数加一
mov cx, ax ;将ax里的商给cx jcxz d2 ;若cx为0,则执行d2 jmp d1 ;否则跳转到d1
d2: mov cx, dx ;将做除法的高十六位的商给cx jcxz d3 ;若cx=0,则执行标号d3处的代码 jmp d1 ;若cx=0不成立,则执行d1处的代码 d3: mov cx, di ;将进栈字符个数传给cx,作为循环次数 d4: pop ax ;将字符出栈
mov [si], al ;将字符的ASCII码写入数据段 inc si ;指针加1
loop d4 ;循环执行标号d4处的代码 ;循环结束后,寄存器逆序出栈 pop di pop si pop dx pop cx pop ax
Ret ;子程序结束
divdw: ;子程序,做无溢出的除法操作 ;si,ax进栈保护 push si push ax
mov ax, dx ;将被除数的高十六位给ax mov dx, 0 ;高位清0
div cx ;做除法操作,商在ax中,余数在dx中 mov si, ax ;将高位商给si
pop ax ;被除数的低十六位出栈
div cx ;做除法操作,商在ax中,余数在dx中 mov cx, dx ;将余数给cx mov dx, si ;将高位的商给dx pop si ;si出栈 Ret
show_str: ;寄存器进栈保护 push ax push es push bx push si
mov ax, 0b800h ;将显存缓冲区的地址给ax mov es, ax ;ax将值赋给段寄存器 ;计算显示的位置
mov al, 160 ;每行有160个字节
mul dh ;做乘法操作,结果放在ax中