admin 管理员组

文章数量: 887021


2024年1月4日发(作者:sqlite3编码页面)

实验4 涉及压缩BCD码数据的转换程序及DEBUG练习

一、实验内容: 1. ASCII码表示的十进制数转换为压缩型BCD码

2. BCD码转换为十进制数的ASCII码

3. 二进制数转换为BCD码

4. BCD码转换为二进制数

5.应用DEBUG观察上述练习的结果

二、实验目的:1.掌握利用DEBUG进行调试目的程序的方法。

2.学习并理解寻址方式,学习改正错误语句的方法。

3.认识压缩型BCD码与非压缩型BCD码表示方法。

4.学习涉及BCD码的数据转换的方法。

三、知识准备

1. Debug调试程序的使用

是十分重要的调试工具,可以用来以二进制形式查看文件内容、可以进行汇编与反汇编,可以对程序进行跟踪式执行,可以修改寄存器与内存中的数据等等。

命令格式:DEBUG [[<盘符>:][<路径>]<文件名> [<测试参数>]]

注意文件名称必须带扩展名。如果用于汇编程序调试,扩展名只能是.EXE或.COM。在DEBUG命令后若用户键入文件名,则DEBUG将指定的文件装入内存;若用户未键入文件名,则DEBUG对当前存储器中的内容进行操作,也可以用N和L命令将需要的文件装入存储器。

进入调试器后,在界面最左边出现一个减号,这是Debug提示符,表示可以打入Debug命令对可执行程序进行查看、动态跟踪和调试。

Debug的命令是单个字母,不区分大小写,字母后面可以有一或多个参数,命令、参数一般用空格分隔。每输入一个命令,回车后执行。当有错误时,用^和error指示错误所在。如果需要中断执行命令,可以使用Ctrl+Break键。

如果不标志单位,在命令中使用的参数均以16进制数为单位,输入16进制数据时不用在数据后加H。

如果针对当前段,关于地址可以只标明偏移地址。如果为非当前段,要申明段地址,方法是在偏移地址前加段地址说明,用冒号分隔。段地址可以是具体地址数,也可以是段寄存器名。例如,08A3:200,表示段地址为08A3H,偏移地址为200H。又例如,DS:200,表示为当前数据段中,偏移地址为200H。

当欲显示内存中数据时。如果仅给1个地址参数,表示显示从该地址起,共8小段数据,如果参数为二个地址,之间用空格分隔,表示按该地址范围显示,但如果范围太大。只能看见最后一部分数据。地址范围还可以书写为[<段地址>:]<起始地址> L <长度>”,例如CS:100 L 10,它所指的地址范围和CS:100 10F是一致的。

命令如果不符合DEBUG的命令规则将产生错误,会出现“error”提示,并用“∧”提示错误位置。

最常用的几个命令:

1)D

意义:显示内存中具体地址起8小段或某个范围内存放的数据的16进制码,并变换为ASCII码以作对照。

格式:D ; 查看内存中当前位置起8小段内存放的数据的16进制码。当前位置指上一次操作最后单元的位置。

D<.地址> ;查看指定地址起8小段内存放的数据的16进制码。

D<.地址1> <.地址2> ;查看地址1到地址2范围内存放的数据的16进制码。

2)R

意义:显示寄存器中数据内容,如果指定寄存器,允许修改寄存器中的数据。

格式:R ;显示所有寄存器内的数据及当前IP所指地址内代码的二进制码。

R<寄存器名> ;显示所指定寄存器中的数据,并允许修改其值。

3)G

意义:执行程序

格式:G ; 从当前位置起执行程序。

G=<起始地址> ;从指定地址起执行程序。

G<地址> ;从当前位置起执行程序到所指定地址为止。为止地址可看作断点。

G=<起始地址> <断点地址> ;从起始地址起执行程序,到断点地址为止。

G=<起始地址> <断点地址1> <断点地址2>„„ ;从起始地址起执行程序,到断点地址1为止。停止运行,并显示当前寄存器、标志位的内容和下一条将要执行的指令,按回车键可以从断点处继续向下运行。断点最多可设置10个。

4)T

意义:单步执行程序,每次执行一条语句。

格式:T ;执行当前语句,执行完一句后显示执行之后各寄存器情况和下一条要执行的指令的地址和内容。如果涉及内存单元,会显示该单元地址及其值。

T=<地址> ; 从指定地址起执行一条语句。执行完后显示执行之后各寄存器情况。

-T [=<起始地址>] [<指令条数N>] ; 多条指令跟踪:从指定起始地址开始执行指令,共执行指定的N条指令后停止,每执行一条指令就显示出各寄存器的内容、标志位的状态和下一条要执行的指令的地址和内容。

注意:如果当前指令为中断指令,例如INT 21H,不要进行T单步操作。

5)P

意义:单步或多步执行程序,每次执行一条语句、一个子程序或若干条语句。

格式:P ;执行当前语句,执行完一句或一个子程序后显示执行之后各寄存器情况。如果涉及内存单元,会显示该单元地址及其值。

P<数字> ;执行N条语句。

P=<地址> ; 从指定地址起执行一条语句或一个子程序。执行完后显示执行之后各寄存器情况。

注意:和T的不同在于如果P后为数字N或当前指令为中断指令、子程序调用等,将视这N条语句或中断程序、子程序整体为一步。如果当前指令为软中断指令INT 21H,应当用P命令跟踪。

6)U

意义:对执行程序进行反汇编,列出各条指令位置、二进制码,及与源程序代码的对照。

格式:U ; 对当前位置起约20H单元中程序代码进行反汇编。

U <.地址> ;对指定地址起约20H单元中程序代码进行反汇编。

U <.地址1> <.地址2> ;对地址1到地址2范围内程序代码进行反汇编。

7)Q

意义:退出Debug,返回DOS。

2. ASCII码与BCD码之间的转换

1)字符的ASCII码表示

计算机中存储的信息很多,其中一部分是用于数学计算的数据,另一部分则是表示某种含义的字符或字符串。由于从键盘输入的或屏幕显示的信息,都是用字符串的形式表示的。因

此,微机中必须能够存储和处理字符和字符串。

计算机中使用的字符包括有如下4类:

·字母:A、B、C、„、Y、Z、a、b、c、„、y和z。

·数字:0、1、2、3、„、9。

·专用符号:!、@、+、-、﹡、/、„ „

·控制字符:BEL(响铃)、LF(换行)、CR(回车)„ „

这些字符在计算机内部都由特定的二进制数表示。目前在微机中,最常用的字符表示法是ASCII码(American Standard Code for Information Interchange,美国标准信息交换码)。在这种表示法中,每一个字符可以表示为一个8位的二进制数,即一个字节。其中。低7位用于表示该字符的ASCII值,最高位未定义,一般可用作奇偶校验位。

常用字符的ASCII码表见表1.2。

2)、十进制数的BCD码表示

BCD码(Binary Code Decimal),又称“二进制表示的十进制数”,是一种非常适合数据输出的编码。一般而言,它可分为如下两种:

(1)、压缩型BCD码:它用4位二进制数表示一位十进制数。即采用二进制数0000~1001分别表示十进制数中的0~9,而另6种组合1010~1111在BCD中则不允许出现;

(2)、非压缩型BCD码:它用8位二进制数,即一个字节表示一位十进制数。其高4位固定为0,而低4位采用二进制数0000~1001分别表示十进制数中的0~9。亦即用0000

0000~0000 1001分别表示十进制数中的0~9。而其余组合则不允许出现。

表1列出了十进制数与BCD编码的对应关系。

表1 BCD编码表

BCD编码

0000

0001

0010

0011

0100

0101

0110

0111

十进制数

0

1

2

3

4

5

6

7

BCD编码

1000

1001

1010

1011

1100

1101

1110

1111

十进制数

8

9

这六种

情况在

BCD码

中不允

许出现

四、 实验程序

1.按如下步骤操作,了解 DEBUG 命令及其使用方法。

(1)打 DEBUG 进入 DEBUG 控制,显示提示符 '_ '。

(2)用命令 F100 10F 'A' 将'A'的ASCII码填入内存。

(3)用命令 D100 10F 观察内存中的16进制码及屏幕右边的ASCII字符。再用命令 D100 观察内存情况,之后接用二个命令D 观察内存情况。再用命令D100:10F

观察内存区的情况,说明这次与上次内存区各个段地址是什么,为什么?

(4)用命令 F110:11F 'A' 重复上二项实验,设法用D命令找到并观察结果,进行比较。

(5)用命令 E100 30 31 32 „„ 3F将30H-3FH写入地址为100开始的内存单元中,再用D命令观察结果,看键入的16进制数是什么字符的ASCII码?

(6)用H命令检查下列各组16进制数加减结果并和你的手算结果比较:

①34H,22H ②56H,78H ③A5,79H ④1284H,5678H ⑤A758,347FH

例如: H 34 22

(7)用R 命令检查各寄存器内容,特别注意AX,BX,CX,DX,IP及标志位中ZF,CF 和AF的内容。

(8)用R命令将AX,BX内容改写为1050H及23A8H。

(9)用A命令在内存100H处键入下列内容:

MOV BX, 8275H

MOV AX,3412H

ADD BX,92A5H

ADC AX,2F65H

ADD BX,EAE6H

ADC AX,9C88H

用U命令检查键入的程序并记录,特别注意左边的机器码。

用T命令逐条运行这些指令,每运行一行检查并记录有关寄存器及IP的变化情况。并注意标志位有无变化。

标志位显示 1 0

CF CY NC

ZF ZR NZ

SF NG PL

AF AC NA

OF OV NV

PF PE PO

DF DN UP

IF EI DI

(1)对照书本中关于 debug操作的介绍对以上实验内容进行总结。

(2)G命令的功能是什么?有那几种格式?

(3)D命令的功能是什么?有那几种格式?

(4)用P命令逐条运行上述指令,与T命令进行比较,阅看书本中关于这二个命令的说明,它们之间有什么不同,在本实验中为什么没有体现?

2.在编译与连接生成执行程序之后利用DEBUG调试该程序,了解不同变量数据存储情况,了解变量的三种含义及用法,了解加法、乘法运算方法及对标志位的影响。(在某些句后给出了单步执行该句后需要思考与记录的问题)。

DATA SEGMENT

A DW 35H,9AC9H

DB 34H

B DW 4CBEH,8872H

DB 34H

C DD 8A607H

DB 34H

D DD 98AB457H

DB 34H

E DB -48H

DATA ENDS

STACK SEGMENT STACK

DB 200 DUP(0)

STACK ENDS

CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE

START:MOV AX,DATA ;数据段在那里?怎样看数据段中的内容?

MOV DS,AX

;在执行一次单步后查看数据区,记录数据是怎样存放的。

;对以下每句运行后分析:这一句的意义是什么?

; 如果是加法,相加的数据是什么?在存储区什么位置?

; 处理的结果在那里?

; 对标志位的影响如何?

; 观察一下,如果去掉“WORD PTR ”编译时会如何?

MOV AX,OFFSET A+2 ;AX中值是多少?意义是什么?

LEA AX,A+2 ; AX中值是多少?意义是什么?

MOV AX,A+2

ADD AX,B+2 ;多少加多少,结果在那里?等于多少?有没有标志改变?

MOV BX,A

ADC BX,B ;多少加多少,结果在那里?等于多少?有没有标志改变?

MOV AX,WORD PTR C

ADD AX,WORD PTR D ;多少加多少?等于多少?有没有标志改变?

MOV AX,WORD PTR C+2

ADC AX,WORD PTR D+2 ;多少加多少?等于多少?有没有标志改变?

;对以下有注释的每句进行分析:数据是如何存放的?运行结果在那里?

; 对CF与OF的影响如何?特别注意进位与符号扩展并不完全对应

MOV AL,E

MOV BL,-3

MUL BL ;多少乘多少,结果在那里?等于多少?有没有标志改变?为什么?

MOV AL,E

MOV BL,3

MUL BL ;多少乘多少,结果在那里?等于多少?有没有标志改变?为什么?

MOV AL,E

MOV BL,-3

IMUL BL ;多少乘多少,结果在那里?等于多少?有没有标志改变?为什么?

MOV AL,E

MOV BL,-1

IMUL BL ;多少乘多少,结果在那里?等于多少?有没有标志改变?为什么?

MOV AL,E

MOV BL,3

IMUL BL ;多少乘多少,结果在那里?等于多少?有没有标志改变?为什么?

MOV BL,-1

MUL BL ;-1=ffh,cf=1。为什么?

MOV AL,58h

MOV BL,-1

iMUL BL ;-1,cf=0,高位全1。为什么?

MOV AL,90h

MOV BL,-1

MUL BL ;-1=ffh,cf=1。为什么?

MOV AL,90h

MOV BL,-1

IMUL BL ;-1,cf=0,高位全0。为什么?

MOV AL,58h

MOV BL,1

MUL BL ;*1,cf=0,高位全0。为什么?

MOV AL,58h

MOV BL,1

iMUL BL ;*1,cf=0,高位全0。为什么?

MOV AL,90h

MOV BL,1

MUL BL ;*1,cf=0,高位全0。为什么?

MOV AL,90h

MOV BL,1

IMUL BL ;*1,cf=0,高位全1。为什么?

MOV AH,4CH

INT 21H

CODE ENDS

END START

(1)乘法运算时使CF与OF为0的情况其实不多见,你能否总结一下大致在什么情况下会出现它们为0的情况?

(2)如果要看到数据中数据的存放情况,一种方法是用D<段地址> <偏移地址>,另一种方法是用DDS:< 偏移地址>。你用什么方法得到段地址?试用这二种方法观察数据区中数据存放情况,A、B、C、D、E的地址各是多少,为什么?

3.检查下面那些指令是错误的,说明原因并改正。(用MASM对该程序进行编译,观察那些语句报错,报的是什么错?再看语句,根据语法与句法分析实际是什么错,在语句后加简单注释,说明错误原因,尝试进行修改,要求尽量使修改结果符合原设计意图。最终要求全部修改后能通过编译。)

DATA SEGMENT

BUF DB 3

DA1 DB ?

C DB 'B',0DH,0AH,'$'

COUNT EQU $-C

DATA ENDS

STACK SEGMENT STACK

DB 200 DUP(0)

STACK ENDS

CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE

START:MOV AX,DATA

MOV DS,AX

MOV DL,255H

INC COUNT

MOV CS,DX

CMP 280,BL

PUSH DX

LEA AL,C

MOV BX,DA1[DX]

SUB [DI],[SI]

ADD [DX],BX

MOV 80H,AX

MOV DA1,AX

ADD [DI],10H

MOV BX,OFFSET DA1

MOV [SI+DI],BX

INC CS

MOV ES,DS

POP AH

ROL AX,2

MOV BX,DA1[DI]

MOV AH,4CH

INT 21H

CODE ENDS

END START

ASCII码与压缩型BCD码的相互转换

4.十进制数的ASCII码转换为压缩型BCD码

令数据段中自ASC_BUF开始的缓冲区内存放着若干个ASCII码表示的十进制数(每个单元存放一位十进制数),要求将这些ASCII码表示的十进制数转换为BCD码,并把两个相邻单元的BCD码合并在一个存储单元(若ASCII码的个数为奇数,则将首地址单元的十进制数对应的BCD码单独存放一个单元,其余的按统一的方法处理)。应用DEBUG跟踪执行程序,当程序执行到语句MOV AH,4CH 时,查看数据区的内容,分析运行结果。通过执行过程深入理解内存储器分段的概念。

本程序中因有的位置使用了中文符号,在编译时会报错,观察是如何报错的?检查问题出现在什么地方,将之改正后重新编译直到通过。

DATA SEGMENT

ASC_BUF DB ‘71542185’

COUNT EQU $-ASC_BUF

BCDBUF DB 10 DUP(?)

DATA ENDS

CODE SEGMENT

ASSUME CS:CODE,DS:DATA,ES:DATA

START: MOV AX,DATA

MOV DS,AX

MOV SI,OFFSET ASC_BUF

MOV DI,OFFSET BCDBUF

MOV CX,COUNT

MOV BX,CX

SHR BX,1 ;BX右移一位,等效于除2

JNC EVEN1 ;(CF)=0,则CX为偶数

MOV BL,[SI] ;对首位单独进行处理

AND BL,0FH

MOV [DI],BL

DEC CX

INC SI

INC DI

EVEN1: MOV AL,[SI]

AND AL,0FH ;清高4位为0

MOV BL,[SI+1]

AND BL,0FH ;清高4位为0

MOV DL,16

MUL DL

ADD AL,BL

MOV [DI],AL

ADD SI,2

INC DI

DEC CX

JNZ EVEN1

MOV AH,4CH

INT 21H

CODE ENDS

END START

(1)画出本程序程序流程图。

(2)将‘71542185’改为‘471542185’,观察结果有何不同,分析程序中判断数字个数奇偶并“对首位单独进行处理”的意义与程序设计方法。

(3)总结将二个十六进制字符拼成一个八位二进制数的程序设计方法。

5.压缩BCD码转换为十进制数的ASCII码

将数据段中字节变量BCD_BUF为首地址的缓冲区中一个八位十进制数对应的压缩BCD码转换为ASCII码,并显示。

DATA SEGMENT

BCD_BUF DB 34H,25H,12H,97H ;十进制数97122534

DATA ENDS

CODE SEGMENT

ASSUME CS:CODE, DS:DATA

MAIN PROC NEAR

PUSH DS

SUB AX,AX

MOV AX,DATA

MOV DS,AX

MOV CX,4

MOV SI,OFFSET BCD_BUF

ADD SI,3

MOV DH,0

CHG_OUT1: PUSH CX

MOV AL,[SI] ;取压缩BCD码

DEC SI ;修改指针

MOV BL,AL ;保存AL

MOV CL,4

ROR AL,CL

AND AL,0FH ;取高半字节BCD码

ADD AL,30H ;生成ASCII码

MOV DL,AL

MOV AH,2

INT 21H ;标准设备输出

MOV AL,BL ;从BL所保存的AL恢复AL

AND AL,0FH ;取低半字节BCD码

ADD AL,30H ;生成ASCII码

MOV DL,AL

MOV AH,2

INT 21H ;标准设备输出

POP CX

DEC CX

JNZ CHG_OUT1

RET

MAIN ENDP

CODE ENDS

END

(1)对本程序不用执行执行文件的方式,而分别用DEBUG单步跟踪、分断点运行等二种方式操作,记录操作过程与执行结果。

(2)总结从一个字节16进制数据获得其二个16进制数码的程序设计方法。

二进制数与BCD码之间的转换

6.二进制数转换为压缩BCD码

将DX寄存器中存放的无符号二进制数(0-65535)转换为压缩BCD码(在程序中自行加一条语句,将一个数保存到DX中),保存在BCD_BUF缓冲区中。应用DEBUG跟踪执行程序,查看数据区的内容,分析运行结果

DATA SEGMENT

BCD_BUF DB 3 DUP(0)

DATA ENDS

CODE SEGMENT

ASSUME CS:CODE, DS:DATA

MAIN PROC NEAR

PUSH DS

SUB AX,AX

MOV AX,DATA

MOV DS,AX

MOV DI,OFFSET BCD_BUF

MOV AL,0

MOV CX,5

CLEAR_BUF: MOV [DI],AL ;初始化缓冲区

INC DI

DEC CX

JNZ CLEAR_BUF

MOV DI,OFFSET BCD_BUF

CHG_BCD1: MOV AX,DX ;转换开始

MOV DX,0

MOV CX,10

DIV CX

MOV BL,DL

MOV DX,0

MOV CX,10

DIV CX

MOV CL,4

SHL DL,CL ;左移4位,等效于乘以16

AND DL,0F0H

OR DL,BL ;组合BCD码

MOV [DI],DL ;存储BCD码

INC DI

MOV DX,AX

CMP DX,0

JNZ CHG_BCD1

RET

MAIN ENDP

CODE ENDS

END

(1)假如保持在DX中数为6440,用debug调试,运行G=0 40,再用DDS:0观察结果。又更换DX中数为26440,用同样方法再看结果。说明结果是怎样存放的。

7.压缩BCD码转换为二进制数

将BX寄存器中的四位压缩型BCD码转换为二进制数,并存放到DX中。应用DEBUG跟踪执行程序,分析运行结果

CODE SEGMENT

ASSUME CS:CODE

START: MOV BX,3698H

MOV SI,BX

XOR AX,AX

MOV CX,4 ;BCD码共4位

CHG_AGAIN1: MOV DI,0

PUSH CX

MOV CX,4 ;每个BCD码对应四位2进制数

CHG_AGAIN2: SHL SI,1 ;SI左移,最高位送CF

RCL DI,1 ;CF最高位送DI

DEC CX

JNZ CHG_AGAIN2 ;将某位BCD码送DI

MOV CX,10

MUL CX

ADD AX,DI ;二进制数合并

POP CX

DEC CX

JNZ CHG_AGAIN1

MOV DX,AX

MOV AH,4CH

INT 21H

CODE ENDS

END START

(1)将以上实验3、4、5、6所要求的压缩BCD码改为要求非压缩BCD码,求设计程序。

(2)第5、6题提到的数说明为二进制数,如果提到的数说明为十六进制数,意义是否相同?


本文标签: 地址 数据 执行 命令