加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

汇编实验报告

(2010-12-01 11:49:41)
分类: 大学实验报告

实验一 汇编程序的汇编及运行

1.实验目的

(1)熟悉汇编程序的汇编、连接、执行过程;

(2)生成LST文件,查看LST文件;

(3)生成OBJ文件,修改语法错误;

(4)生成EXE文件;

(5)执行程序。

2.实验涉及知识

汇编程序从编写到执行的过程

编程→.ASM→编译→.OBJ→连接→.EXE→加载→内存中的程序→执行

1)编写源程序

用EDIT或记事本输入各段,并存储成源程序(保存在MASM目录下),扩展名为ASM。

2)对源程序进行汇编、连接

操作如下:

(1)在DOS状态下,进入MASM目录;

(2)输入命令:MASM 文件名(连同扩展名);

(3)在系统出现的提示中输入:

object filename[.obj]:按回车键。

Source listling[nul.lst]:输入:文件主名,生成lst文件,也可以不生成,直接按回车键。Lst文件用于查看编译为目标文件的过程中产生的中间结果。

Cross-reference [nul.crf]:按回车键。

(4)如果系统没有提示出错,那么编译过程就完成了。如果提示错误则应用edit打开源文件进行修改,然后再重复2和3步骤

(5)输入:link 文件主名(不要输扩展名,也可以输入扩展名.obj)

run file [.exe]:按回车键。

List file [nul.map]:按回车键。

Libraries [.lib]:按回车键。

(6)没有提示错误,汇编过程就结束了,产生了exe可执行文件。如果出现‘no strack segment’的错误警告,不用理会。

3)执行程序(由DOS中的COMMAND命令将文件加载入内存)

在DOS提示符下直接输入文件主名就可以执行文件了。程序执行后,有的会显示结果,有的可能执行后什么结果都没有,是因为程序中没有显示命令。

3.实验内容

1)将下面的数据段输入,取名1.ASM,保存在MASM文件夹下。生成LST文件,(不必连接、运行)用EDIT查看1.LST文件。试回答:DA1,DA2的偏移量分别是多少?COUNT的值为多少?

DATA SEGMENT

ORG 20H

NUM1=8

NUM2=NUM1+10H

DA1 DB ‘IBM PC’

DB 0AH, 0DH

COUNT EQU $-DA1

DATA ENDS

END

2)输入下面错误的文件,修改错误语句。(MASM没有出现错误即可。不必连接、运行。)

DATA SEGMENT

VAR1 DB 0, 25, ODH, 300

VAR2 DB 12H, A4H, 6BH

VAR3 DB ’ABCDEF’

VAR4 DW 1234H, 5678H

VAR5 DW 10H DUP(?)

DATA ENDS

CODE SEGMENT

ASSUME CS: CODE, DE: DATA

BEING MOV AX, DATA

MOV DS, AX

LEA SI, VAR5

MOV BX, OFFSET VAR2

MOV [SI], 0ABH

MOV AX, VAR1+2

MOV [BX], [SI]

MOV VAR5+4, VAR4

MOV AH, 4CH

INT 21H

CODE ENDS

END START

3)输入下面程序并运行

STACKS SEGMENT STACK

DW 128 DUP(?)

STACKS ENDS

DATAS SEGMENT

STRING DB ‘WELCOME!’, 13, 10, ‘$’

DATAS ENDS

CODES SEGMENT

ASSUME CS: CODES, DS: DATAS

START: MOV AX, DATAS

MOV DS, AX

LEA DX, STRING

MOV AH, 9

INT 21H

MOV AH, 4CH

INT 21H

CODES ENDS

END START

4.实验结果

(1)

http://s6/middle/6ea6cd6a496512ac1ada5&690

所以DA1的偏移量为20,count的值为8。

分析过程:org伪指令用来设置当前地址计数器的值,EQU和=伪指令是不占存储空间的,所以DA1的偏移地址为20;$是表示当前地址计数器的值,又因为DA1存的是字节类型,所以COUNT EQU $-DA1指令就是求count的值为8。

(2)

http://s9/middle/6ea6cd6a496512af9b308&690

应用edit打开源文件进行修改

http://s2/middle/6ea6cd6a496512b05a0f1&690

因为O不在十六进制里面,所以应该把O DH改为0DH,因为VAR1是字节类型,所以数字最大范围为255,所以把300是错误的,改为30;第九行应该把DE改为DS.

http://s11/middle/6ea6cd6a496512b1d3a6a&690

MOV指令中,立即数传送给内存单元时要说明是送到一个内存单元还是两个内存单元,所以十四行应改为MOV BYTE PTR[SI],0ABH。而且MOV OPD,OPS中的OPD和OPS的位数必须一致,所以第十五行应改为MOV AL,VAR1+2.由于MOV指令的OPD和OPS不能同时是内存单元,所以需要把第十六行改为MOV BX,SI.需要在两个内存中传数据,得先把一个内存单元内容移到寄存器,所以第十七行改为MOV AX,VAR4 MOV VAR5+4,AX。

下面为修改后的结果:

http://s13/middle/6ea6cd6a496512b30016c&690

(3)

编译:

http://s13/middle/6ea6cd6a496512b622ddc&690

连接:

http://s13/middle/6ea6cd6a496512b7d408c&690

执行:

http://s7/middle/6ea6cd6a496512bb94c26&690

5.实验总结

通过本次实验,我熟练掌握了如何使用汇编环境,掌握了如何编译、如何连接、如何执行命令,还熟悉了点如何修改错误语句。

实验二DEBUG的使用

1.实验目的

(1)学习使用DEBUG的命令;

(2)使用DEBUG命令在数据段中查看程序运行的结果;

(3)利用DEBUG运行简单的程序段。

2.实验内容

1)输入程序观察寄存器变化

使用DEBUG命令,将下面的程序段写入内存,逐条执行,观察每条指令执行后,CPU中相关寄存器的内容变化。注意用T命令执行时,CS: IP寄存器的内容

MOV AX, 4E20

ADD AX, 1416

MOV BX, 2000

ADD AX, BX

MOV BX, AX

ADD AX, BX

MOV AX, 001A

MOV BX, 0026

ADD AL, BL

ADD AH, BL

ADD BH, AL

MOV AH, 0

ADD AL, BL

ADD AL, 9C

2)输入下面的程序,这是一个两个数相与的程序。结果存放在MSG2单元中,偏移地址为?值为多少?

DSEG SEGMENT

MSG1 DW 7856H, 2038H

MSG2 DW ?

DSEG ENDS

CSEG SEGMENT

ASSUME CS: CSEG, DS: DSEG

START: MOV AX, DSEG

MOV DS, AX

MOV AX, MSG1

AND AX, MSG1+2

MOV MSG2, AX

MOV AL, 0

MOV AH, 4CH

INT 21H

CSEG ENDS

END START

程序的跟踪执行操作

在DOS下直接输入文件主名就可以执行文件了,有的程序会显示结果,可能执行后什么结果都没有,是因为程序中没有显示命令。那么如何查看程序的运行结果呢?

程序执行过程的跟踪操作步骤如下:

(1)在DOS下输入:DEBUG 文件名.EXE

(2)在DEBUG提示符下输入U命令

如果程序中有数据段,可以看到反汇编后第一句可执行语句为:

A地址:B地址 MOV AX, K地址 如:1261:0000 MOV AX, 1260

其中:K地址就是数据段的段寄存器内容,A地址为代码段段寄存器地址,B地址为程序第一条指令的偏移地址。

(3)可以用T命令单步执行指令,执行到 MOV AH, 4CH时结束,也可以用G命令执行整个程序,输入:G=B地址(如:G=0000)

(4)用D命令查看程序执行后数据段的变化

输入:D K地址:0 (如:D1260:0)

在显示的数据中,对照源程序或LST文件查看结果所在的偏移地址的内容。

3. 实验结果

1. http://s5/middle/6ea6cd6a496512bc6e564&690

http://s9/middle/6ea6cd6a496512bcf4718&690

http://s15/middle/6ea6cd6a496512be4315e&690

http://s7/middle/6ea6cd6a496512c068896&690

2)反汇编u:

http://s15/middle/6ea6cd6a0756e8468694e&690

用t单步执行:

http://s11/middle/6ea6cd6a496512cb0c0da&690

因为AND是逻辑与运算指令,对相与的两个数都为1的时候,值才为1.所以在单步执行AND AX,[0002]后,AX寄存器内的值变为2010.又MOV 【0004】,AX,所以MSG2的值为2010H。

用D命令查看程序执行:

http://s6/middle/6ea6cd6a496512cc88045&690

用edit查看:

http://s13/middle/6ea6cd6a0756e847c317c&690

由上图可知,MSG2的偏移地址为0004。

4.实验总结

通过这次实验,掌握了了使用debug的命令,还有怎么使用debug命令在数据段中查看程序运行的结果。我明白了,debug是一种很好的调试程序工具。

实验三 顺序程序设计

1、 实验目的

(1) 熟练使用DEBUG命令。

(2) 学习使用简单的汇编指令编写程序。

(3) 了解循环语句的执行过程

2、 实验内容

1)下列程序单步运行,注意AL,BX,CX寄存器的变化,并观察数据段字母的变化。如果是将小写字母改成大写字母带注释的语句该如何修改?

DSEG SEGMENT

MSG1 DB ‘abc’

DSEG ENDS

CSEG SEGMENT

ASSUME CS: CSEG, DS: DSEG

START: MOV AX, DSEG

MOV DS, AX

LEA BX, MSG1

MOV CX, 3

S: MOV AL, [BX]

AND AL, 11011111B ;将AL中的ASCII码的第5位置0,

;变成大写字母。

MOV [BX], AL

INC BX

LOOP S

MOV AL, 0

MOV AH, 4CH

INT 21H

CSEG ENDS

END START

2)编写调试下面的程序,用DEBUG查看数据段中的结果

http://s15/middle/6ea6cd6a496512ce78f1e&690,X,Y,W为字节类型变量,结果存于Z单元,写出数据段和代码段。

3)编写程序。X,Y为字节类型数,求http://s16/middle/6ea6cd6a0756e847ec9cf&690,写出完整的数据段和代码段,不用乘除指令。

3、 实验结果

1.反汇编

http://s8/middle/6ea6cd6a496512cfe2f77&690

单步执行:

http://s16/middle/6ea6cd6a496512d192fbf&690

http://s7/middle/6ea6cd6a0756e8483cc26&690

http://s1/middle/6ea6cd6a496512d372e90&690

http://s10/middle/6ea6cd6a496512d3d91f9&690

http://s14/middle/6ea6cd6a496512d525a6d&690

http://s7/middle/6ea6cd6a496512d59bd26&690

如果是将小写字母改成大写字母,只要把AND AL,11011111B改成OR AL,00100000B就可以。因为小写字母比大写字母的十六进制ASCII码大了20H,所以只要把把AL中的ASCII码的第六位置1即可。

3.

(1)

http://s11/middle/6ea6cd6a496512d74be4a&690

调试结果:

http://s16/middle/6ea6cd6a496512d831b3f&690

所以修改程序:

http://s8/middle/6ea6cd6a0756e84900097&690

调试结果:

http://s13/middle/6ea6cd6a496512db1554c&690

使用debug查看:

反汇编

http://s8/middle/6ea6cd6a496512db54087&690

单步执行:

http://s7/middle/6ea6cd6a496512dd05b36&690

http://s7/middle/6ea6cd6a0756e84961f36&690

http://s11/middle/6ea6cd6a496512dede27a&690

(2)

http://s13/middle/6ea6cd6a0756e849abd2c&690

调试结果:

http://s5/middle/6ea6cd6a496512e10e274&690

使用debug

反汇编

http://s1/middle/6ea6cd6a496512e2bc8e0&690

单步执行

http://s2/middle/6ea6cd6a496512e2e5311&690

http://s16/middle/6ea6cd6a496512e77ab0f&690

http://s6/middle/6ea6cd6a496512e838625&690

http://s6/middle/6ea6cd6a0756e84a7fc55&6904.实验总结

通过本次实验,我学会了使用简单的汇编指令编写程序。并掌握了循环语句的执行过程。

实验四 程序的调试及循环语句

1.实验目的

(1)学习调试程序,查找逻辑错误;

(2)学习分支语句的编程和调试;

(3)学习循环语句的编程和调试。

2.实验内容

1)有10个数,统计正数的个数,存放在变量M中中。经过汇编后,形成EXE文件。在DEBUG中,先用G=0命令执行程序,用D命令查看M单元的内容,会发现结果不正确。用单步执行命令T=0,单步执行程序,查找程序中的逻辑错误,注意每一次循环中AL寄存器中值的变化是否正确?(AL寄存器中存放正数的个数)

DSEG SEGMENT

MSG DB 4, -2, -6, 0, 5, 67, 8, -3, 5, 6

M DB ?

DSEG ENDS

CSEG SEGMENT

ASSUME CS: CSEG, DS: DSEG

START: MOV AX, DSEG

MOV DS, AX

MOV CX, 10

MOV AL, 0

LEA SI, MSG

L1: MOV BL, [SI]

CMP BL, 0

JBE NEXT

INC AL

NEXT: INC SI

LOOP L1

MOV M, AL

MOV AL, 0

MOV AH, 4CH

INT 21H

CSEG ENDS

END START

2)数据段中是一组无符号数,将最小数存放在M单元中。按上题方法查找一处逻辑错误。

DSEG SEGMENT

MSG DB 13, 15, 7, 25, 24

M DB ?

DSEG ENDS

CSEG SEGMENT

ASSUME CS: CSEG, DS: DSEG

START: MOV AX, DSEG

MOV DS, AX

MOV CX, 4

MOV AL, MSG

MOV SI, OFFSET MSG+1

L1: CMP AL, [SI]

JB NEXT

MOV AL, [SI]

NEXT: LOOP L1

MOV M, AL

MOV AL, 0

MOV AH, 4CH

INT 21H

CSEG ENDS

END START

3)编程:在首地址为BUF开始的内存单元中存有10个字节数,求其中0的个数,并将结果存于RESULT中。

4)编程:http://s10/middle/6ea6cd6a496512e991619&690,Ai,Bi为字节型无符号数,分别存于NUM1和NUM2开始的连续存储单元中,结果存于REST单元中。

3.实验结果

1)编译http://s10/middle/6ea6cd6a496512eb0c689&690

结果明显错误,单步执行:

http://s13/middle/6ea6cd6a496512ec395ec&690

http://s15/middle/6ea6cd6a0756e84ae9a9e&690

当4h和0比较,结果正确,使得SI和AX都自增加一,即AX=1,SI=1;

http://s10/middle/6ea6cd6a496512eee6989&690

http://s9/middle/6ea6cd6a496512ef4b758&690

从这边可以看出,-2h和0比较,结果AX和SI 也自增加一,这不是我们要结果,认真查看代码,原来是使用了JBE指令,JBE指令是无符号数比较状态转移指令。而我们需要的是统计正数的个数,所以,明显是要有符号数比较状态转移指令。因此把JBE指令改为JLE.

http://s13/middle/6ea6cd6a496512f0c51cc&690

http://s8/middle/6ea6cd6a0756e84b63ce7&690

http://s14/middle/6ea6cd6a496512f2caccd&690

从这边可以看出这正是我们要的结果,-2h和0比较,使得SI自增加一,而AL不加一。因为AL记录的是正数的个数。

所以直接执行,得到如下

http://s14/middle/6ea6cd6a0756e84b930dd&690

得到六个正数,所以得到修改后的代码是正确的。

2)编译:

http://s8/middle/6ea6cd6a496512f421557&690

得到最小值为13,明显不对,所以单步执行:

http://s14/middle/6ea6cd6a496512f5cfb1d&690

http://s7/middle/6ea6cd6a496512f5f7916&690

从这可以看出是SI没自增加一,导致无限循环。修改代码,在NEXT:后面添加INC SI.

http://s3/middle/6ea6cd6a496512f7716f2&690

http://s7/middle/6ea6cd6a496512f999166&690

http://s7/middle/6ea6cd6a496512fb4cf36&690

在此可以看到,SI=0002和AX=0b13的时候,比较得到SI小于AX,所以赋值给AX,等于07.

所以继续执行得到

http://s16/middle/6ea6cd6a0756e84c6831f&690

得到SI=4,AX=07,根据题目要求,证明了这个结果是正确的。

3)根据题目,(编程见附录),编译通过:

http://s15/middle/6ea6cd6a496512fd707be&690

http://s1/middle/6ea6cd6a0756e84cea160&690

检查1,0,3,-5,0,2,4,6,5,1这组数,可以得到只有两个数的值为0。所以所编的程序是正确的。

4)根据题目要求,编程代码见附录,运行编译如下:

http://s11/middle/6ea6cd6a496513026eaaa&690

http://s2/middle/6ea6cd6a496513041e6c1&690

验证答案,结果是为78h,为正确答案,所以程序正确。

4.实验总结

通过这次实验,我学习到了调试程序,及如何查找逻辑错误;学习分支语句的编程和调试;学习循环语句的编程和调试。

附录:

程序代码如下:

3)

;计算0的个数

STACKS SEGMENT STACK

DW 128 DUP(?)

STACKS ENDS

DSeg Segment

buf db 1,0,3,-5,0,2,4,6,5,1

result db ?

DSeg ends

CSeg Segment para public 'CODE'

Assume cs:CSeg,ds:DSeg

Start: mov ax,DSeg

mov ds,ax

mov al,0

lea si,buf

mov cx,10

again: cmp BYTE PTR[si],0

jne l3

inc al

l3: inc si

loop again

mov result,al

mov bl,al

mov bh,0

mov al,0

mov ah,4ch

int 21h

CSeg ends

end Start

4)

;Y=∑Ai*Bi ,i=1—8 , Ai, Bi为字节型无符号数,分别存于NUM1和NUM2开始的连续存储单元中,结果存于REST单元中。

DSeg Segment

num1 db 1h,2h,3h,4h,5h,6h,7h,8h

num2 db 8h,7h,6h,5h,4h,3h,2h,1h

rest dw ?

DSeg ends

CSeg Segment para public 'CODE'

Assume cs:CSeg,ds:DSeg

Start: mov ax,DSeg

mov ds,ax

mov cx,8

mov bx,0

mov si,offset num1

mov di,offset num2

again: mov al,[si]

mul byte ptr[di]

add bx,ax

inc di

inc si

loop again

mov rest,bx

mov al,0

mov ah,4ch

int 21h

CSeg ends

end Start

实验五 DOS功能调用

1.实验目的

(1)学会DOS中关于显示功能调用指令的用法;

(2)领会修改显存方法显示字符。

2.实验内容

1)输入一个字符,显示出来。

2)输入一个字符串,显示出来

3)BUF开始的3个16位二进制数用十六进制数的形式显示出来。

(1)理解程序

(2)输入程序,汇编,运行(在DOS状态下输入:文件名.EXE),观察结果。

(3)如果要分行显示,程序要如何修改?

DATA SEGMENT

BUF DW 4F59H, 56A8H, 0FF90H

DATA ENDS

CODE SEGMENT

ASSUME CS: CODE, DS: DATA

START: MOV AX, DATA

MOV DS, AX

MOV SI, 0

P: MOV BX, BUF[SI]

MOV CH, 4

L: MOV CL, 4

ROL BX, CL

MOV DL, BL

AND DL, 0FH

CMP DL, 10

JB NEXT

ADD DL, 7

NEXT: ADD DL, 30H

MOV AH, 2

INT 21H

DEC CH

JNZ L

INC SI

INC SI

CMP SI, 4

JNA P

MOV AH, 4CH

INT 21H

CODE ENDS

END START

4)直接改变显存内容显示。

(1)显存空间分配:

内存地址空间中,B8000H-BFFFFH共32KB的空间,为80×25彩色字符模式显示缓冲区。向这个地址空间写入数据,写入的内容将立即出现在显示器上。

80×25=2000个字符,每个字符在缓冲区中占2个字节,一个字节存放ASCII码,一个字节存放字符属性(字符颜色、字符背景颜色、闪烁、高亮度)

(2)偏移地址计算:

如第2行,第40列:(2-1)×160+40×2 这个偏移地址中存放字符的ASCII码,

(2-1)×160+40×2+1这个偏移地址中存放字符的属性。

第M行,第N列的一般计算公式为:

(M-1)×160+N*2 存放ASCII码

(M-1)×160+N*2+1 存放属性

(3)运行下列程序,在屏幕的第1行,会显示一个字符X。根据上面(1)、(2)点理解程序段。

STACK SEGMENT

DB 128 DUP (0)

STACK ENDS

CSEG SEGMENT

ASSUME CS: CSEG, SS: STACK

START: MOV AX, STACK

MOV SS, AX

MOV SP, 128

MOV AX, 0B800H

MOV ES, AX

MOV AH, ‘X’

S: MOV ES: [160*1+40*2], AH

MOV AL, 0

MOV AH, 4CH

INT 21H

CSEG ENDS

END START

5)编程显示以下图案。

*********

*******

*****

***

*

6)编写程序,统计字缓冲区中的20个数据的正数、负数、0的个数,并将统计结果以16进制形式显示出来。

3.实验结果

1

http://s8/middle/6ea6cd6a49651304460d7&690

2)程序代码见附录,编译如下:

http://s4/middle/6ea6cd6a49651304cb7a3&690

3)原程序运行结果

http://s14/middle/6ea6cd6a0756e84d64bdd&690

修改后的代码运行结果

http://s14/middle/6ea6cd6a49651306d1f6d&690

4)运行结果如下:

http://s9/middle/6ea6cd6a49651306be428&690

5)代码见附录,结果如下:

http://s11/middle/6ea6cd6a49651307588da&690

6)代码见附录,结果如下:

http://s2/middle/6ea6cd6a4965130bbf941&690

4.实验总结

通过这次实验,我知道写程序需要注意的一些细节。字符串的输入时,第一个字节是由系统自动生成的,所以要输出用户的字符串,要在用mov dx,offset buf+2。计数时用cx和bx,不能用ch和bh。还有jmp的功能,无条件转移。

附录

1)

STACKS SEGMENT STACK

DW 128 DUP(?)

STACKS ENDS

CSeg Segment para public 'CODE'

Assume cs:CSeg

Start:

mov AH,1

INT 21H

mov al,0

mov ah,4ch

int 21h

CSeg ends

end Start

2)STACKS SEGMENT STACK

DW 128 DUP(?)

STACKS ENDS

DSeg Segment

mesg db 0dh,0ah,'$'

buf db 20

db ?

db 20 dup(?)

DSeg ends

CSeg Segment para public 'CODE'

Assume cs:CSeg,ds:DSeg

Start: mov ax,DSeg

mov ds,ax

mov ah,10

mov dx,offset buf

int 21h

lea dx,mesg ;回车换行

mov ah,09h

int 21h

mov ah,9

mov dx,offset buf+2

int 21h

mov al,0

mov ah,4ch

int 21h

CSeg ends

end Start

3)修改后的代码

DATA SEGMENT

mesg db 0db,0ah,’$’

BUF DW 4F59H, 56A8H, 0FF90H

DATA ENDS

CODE SEGMENT

ASSUME CS: CODE, DS: DATA

START: MOV AX, DATA

MOV DS, AX

MOV SI, 0

P: MOV BX, BUF[SI]

MOV CH, 4

L: MOV CL, 4

ROL BX, CL

MOV DL, BL

AND DL, 0FH

CMP DL, 10

JB NEXT

ADD DL, 7

NEXT: ADD DL, 30H

MOV AH, 2

INT 21H

DEC CH

JNZ L

INC SI

INC SI

CMP SI, 4

lea dx,mesg ;回车换行

mov ah,09h

int 21h

JNA P

MOV AH, 4CH

INT 21H

CODE ENDS

END START

5)STACKS SEGMENT STACK

DW 128 DUP(?)

STACKS ENDS

DSeg Segment

mesg db 0dh,0ah,'$'

buf db 10 dup(?)

DSeg ends

CSeg Segment para public 'CODE'

Assume cs:CSeg,ds:DSeg

Start: mov ax,DSeg

mov ds,ax

mov si,1

mov bx,9

contiue:mov cx,bx

next: mov dl,'*'

mov ah,2

int 21h ;显示

loop next

lea dx,mesg ;回车换行

mov ah,09h

int 21h

dec bx

dec bx

inc si

cmp si,5

jbe contiue

mov al,0

mov ah,4ch

int 21h

CSeg ends

end Start

6);有数据段

STACKS SEGMENT STACK

DW 128 DUP(?)

STACKS ENDS

DSeg Segment

buf db 0h,-1h,5h,1h,0h,-10h,-2h

numb equ $-buf

cout1 dw ? ;0的个数

cout2 dw ? ;正数的个数

cout3 dw ? ;负数的个数

DSeg ends

CSeg Segment para public 'CODE'

Assume cs:CSeg,ds:DSeg

Start: mov ax,DSeg

mov ds,ax

lea si,buf

mov cx,0

lp: mov al,[si]

cmp al,0

jnl next

inc cout3

jmp last

next:je contiue

inc cout2

jmp last

contiue:inc cout1

last: inc si

inc cx

cmp cx,numb

jl lp

mov bx,cout1

call DISP

mov bx,cout2

call DISP

mov bx,cout3

call DISP

mov al,0

mov ah,4ch

int 21h

DISP PROC ;显示BX中的数

mov ch,4

roll: mov cl,4

rol bx,cl

mov dl,bl

and dl,0fh

cmp dl,9

jbe next1

add dl,07h

next1: add dl,30h

mov ah,02h

int 21h

dec ch

jnz roll

RET

DISP ENDP

CSeg ends

end Start

实验六 子程序设计

1.实验目的

(1)学习子程序的编写,主子程序的调用;

(2)不同模块间程序的调用和调试。

2.实验内容

1)数据段中的3个字符,调用子程序将其逐个显示出来。子程序的功能是显示一个字符。单步执行,对CALL语句和RET语句观察SP,IP的变化,并用D命令查看栈顶的内容。

DATA SEGMENT

MAG DB ‘ABC’

DATA ENDS

CODE SEGMENT

ASSUME CS: CODE, DS: DATA

START: MOV AX, DATA

MOV DS, AX

MOV SI, 0

MOV CX, 3

LL: MOV DL, MAG[SI]

CALL MADD

INC SI

LOOP LL

MOV AH, 4CH

INT 21H

MADD PROC

MOV AH, 02H

INT 21H

RET

MADD ENDP

CODE ENDS

END START

2)阅读S31.ASM和S32.ASM两个模块中的程序,并分别汇编,然后连接成一个可执行文件S31.EXE。

具体步骤如下:

MASM S31.ASM(分别汇编)

MASM S32.ASM

LINK S31 S32 (将两个文件连接成为一个文件名为S31)

S31.EXE (运行)

3)编程:利用主程序调用子程序,比较BUF1和BUF2缓冲区中不相等的字符,并将不相等的字符显示出来。(也可以将找到的不相等字符逐个显示,用INT 21H的02功能调用)

4)编程:子程序搜索指定字符缓冲区中是否有N,如果有用Y替代。调用子程序将BUF1,BUF2,BUF3中的N全部用Y替代。

3.实验结果

1.

http://s4/middle/6ea6cd6a0756e84df5a03&690

2.编辑s31和s32文件,输入程序,保存。打开命令提示符运行:

http://s3/middle/6ea6cd6a4965130c8b452&690

编译s32文件:http://s2/middle/6ea6cd6a4965130d10571&690

http://s15/middle/6ea6cd6a4965130ddef0e&690

链接s31和s32文件:http://s12/middle/6ea6cd6a4965131178fbb&690

无错误输出,运行程序:http://s1/middle/6ea6cd6a49651319190e0&690

3.代码见附录,结果如下:

http://s13/middle/6ea6cd6a0756e84f63b1c&690

4.代码见附录,结果如下

http://s10/middle/6ea6cd6a4965131ad93d9&690

4.实验总结

通过这次实验,我知道了写代码要细心,有的错误是隐藏的,编译是检查不出的错误。指令的参数的使用。

附录:

2. NAME S31.ASM

不同模块间的段间调用。从键盘输入2位非压缩BCD数,存入AX寄存器中。为了将其转换为二进制数,编写一个子程序TRAN。显示子程序DISP完成将16进制数转换为对应的ASCII码并显示该字符,显示子程序在另一模块S32中。输入数据为00时结束。

EXTRN DISP: FAR

CODE SEGMENT PARA ‘CODE’

ASSUME CS: CODE

START: MOV AH, 01H

INT 21H

MOV BL, AL

INT 21H

MOV AH, AL

MOV AL, BL

CMP AX, 3030H

JE EXIT

CALL NEAR PTR TRAN

CALL FAR PTR disp

JMP START

EXIT: MOV AH, 4CH

INT 21H

TRAN PROC NEAR ;将输入的ASCII码转换成2进制数

AND AX, 0F0FH ;将ASCII码转换成非压缩BCD码,

;高位在AL中

MOV BL, AH

MOV CL, 10D

MUL CL

ADD AL, BL

RET

TRAN ENDP

CODE ENDS

END START

NAME S32.ASM

PUBLIC DISP

CODE1 SEGMENT PARA ‘CODE’

ASSUME CS: CODE1

DISP PROC FAR

MOV BL, AL

MOV BH, 00

MOV CH, 4

ROLL: MOV CL, 4

ROL BX, CL

MOV DL, BL

AND DL, 0FH

CMP DL, 9

JBE NEXT1

ADD DL, 07H

NEXT1: ADD DL, 30H

MOV AH, 02H

INT 21H

DEC CH

JNZ ROLL

RET

DISP ENDP

CODE1 ENDS

END

3.

data segment

buf1 db " aabbccvvxx$"

buf2 db " aabccvvvxz$"

buf3 db 20 dup(?)

data ends

code segment

assume cs:code,ds:data

start:mov ax,data

mov ds,ax

mov si,0

mov di,0

call bijiao

lea dx,buf3

mov ah,09h

int 21h

mov ax,4c00h

int 21h

bijiao proc

mov al,[si]

cmp al,'$'

je exit

mov ah,buf2[si]

cmp al,ah

je next

mov buf3[di],al

mov buf3[di+1],ah

add di,2

next:inc si

jmp bijiao

exit:mov buf3[di],al

ret

bijiao endp

code ends

end start

4.

;有数据段

STACKS SEGMENT STACK

DW 128 DUP(?)

STACKS ENDS

DSeg Segment

mesg db 0dh,0ah,'$'

buf1 db "YYNYYN$"

numb1 equ $-buf1

buf2 db "NNNNYY$"

numb2 equ $-buf2

buf3 db "YYYNNN$"

numb3 equ $-buf3

buf db 20 dup(?)

DSeg ends

CSeg Segment para public 'CODE'

Assume cs:CSeg,ds:DSeg

Start: mov ax,DSeg

mov ds,ax

lea si,buf1

mov cx,numb1

call modify

call disp

lea si,buf2

mov cx,numb2

call modify

call disp

lea si,buf2

mov cx,numb2

call modify

call disp

mov ah,4ch

int 21h

modify proc

lp: cmp byte ptr[si],'N'

jne contiue

mov al,'Y'

mov buf[si],al

inc si

jmp lp

contiue: mov ah,[si]

mov buf[si],ah

inc si

loop lp

mov ah,9

lea dx,buf

int 21h

ret

modify endp

disp proc

lea dx,mesg ;回车换行

mov ah,09h

int 21h

ret

disp endp

CSeg ends

end Start

实验七 字符处理程序设计

1.实验目的

(1)熟悉串操作指令的功能与应用;

(2)掌握串操作指令的寻址方式及使用方法,编写常用的字符串处理程序。

2.实验内容

从键盘键入一个字符串,存入内存BUF为首地址的单元中,现要求统计其中含有小写字母的个数,并将统计结果以两位十进制数形式显示在屏幕上。

3.调试过程

http://s6/middle/6ea6cd6a4965131bb8805&690

因为程序中有三处单词写错了,修正后,就ok了.但是虽然没有编译时没出现错误,运行时出现了下面的错误.

http://s5/middle/6ea6cd6a4965131c53934&690

仔细分析,原来dos系统功能调用的程序落下了很重要的一句话:mov ah,2

4.实验结果

http://s1/middle/6ea6cd6a0756e84fbf610&690

5.实验总结

通过这次实验,我知道作为一个程序员来说,细心是必须的,否则一个小错误,就会让你焦头烂额。

附参考源程序:

DATA SEGMENT

BUF DB 90 DUP(?)

DATA ENDS

CODE SEGMENT

ASSUME CS: CODE, DS: DATA

START: MOV AX, DATA

MOV DS, AX

MOV CX, 0

LEA DI, BUF

AGAIN: MOV AH, 1

INT 21H

CMP AL, 0DH

JZ DONE

MOV [DI], AL

INC DI

INC CX

JMP AGAIN

DONE: MOV DL, 0DH

MOV AH, 2

INT 21H

MOV DL, 0AH

MOV AH,2

INT 21H

LEA SI, BUF

MOV CH, 0

MOV BL, 0

CLD

NEXT1: LODSB

CMP AL, 61H

JB NEXT2

CMP AL, 7AH

JA NEXT1

INC BL

NEXT2: LOOP NEXT1

MOV AL, BL

MOV AH, 0

MOV CL, 10

DIV CL

XCHG AH, AL

PUSH AX

MOV DL, AH

OR DL, 30H

MOV AH, 2

INT 21H

POP AX

MOV DL, AL

OR DL, 30H

MOV AH,2

INT 21H

MOV AH, 4CH

INT 21H

CODE E NDS

END START

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有