汇编语言程序设计 实验1 用机器指令和汇编指令编程

时间:2024-02-20 16:46:55

汇编语言程序设计 实验1 用机器指令和汇编指令编程

一、实验目的

  1. 熟练掌握使用debug工具编写和调试x86汇编命令的方法
  2. 掌握8086CPU、寄存器、内存的基础知识
  3. 理解并掌握内存中多字节数据的存放:小端法
  4. 理解并掌握「栈」内存空间的特性和使用
  5. 掌握指令mov, add, sub, jmp, push, pop的基础用法

二、实验内容及结果

(一)汇编语言(王爽第4版)实验1 查看CPU和内存,用机器指令和汇编指令编程

1、实验准备

(1)DOSBox的安装

超级贴心的老师已经准备好了Windows平台下的下载安装程序(DOSBox0.74-3-win32-installer),以及Mac OS下的安装镜像(DOSBox-0.74-3-2.dmg),下载好之后一步一步按照老师的教程也可以顺利使用啦!

链接:https://pan.baidu.com/s/1xkV_L_4G42AvKPidYu_czA   提取码:1314

(2)Debug的使用
① 常用的Debug功能

R命令:查看、改变CPU寄存器的内容

D命令:查看内存中的内容

E命令:改写内存中的内容

U命令:将内存中的机器指令翻译成汇编指令

T命令:执行一条机器指令

A命令:以汇编指令的格式在内存中写入一条机器指令

P命令:执行汇编程序,单步跟踪。(与T命令的不同:P命令不会跟踪进入子程序或软中断。)

Q命令:退出Debug,回到DOS状态。

② 在DOSbox中进入Debug

输入命令

mount d: d:\masm

如下图所示,可以在指定盘中运行Debug程序

③用R命令查看、改变CPU寄存器的内容

需要注意的是CS和IP的值,CS=073F,IP=0100,也即内存073F:0100处的指令为CPU当前要读取、执行的指令。

Debug还列出了CS:IP所指向的内存单元处所存放的机器码,并将它翻译成汇编指令,此处CS:IP所指向的内存单元为073F:0100,存放的机器码为0000,对应的汇编指令为ADD [BX+SI],AL。感觉这条指令挺特别的就在网上搜了搜,就是把al的值与ds:[bx+si]的值相加,然后将结果放到ds:[bx+si]中(但其实好像没啥意义,就是0000反编译而成的TAT)。右下角还有一个DS:0000=CD,网上查了之后得知:DS:0000就是这个DS的数据段偏移量0000的地址,[0000]就是进阶寻址这个数据,看到是CD。

同时,R命令也可以用来改变CPU寄存器的内容,如下图所示:

④用D命令查看内存中的内容

用D命令直接查看,将列出Debug预设的地址处的内容,如图所示:

可以用”d段地址:偏移地址“的格式来查看内存某处的内容,如图所示:

⑤用E命令改写内存中的内容

可以用E命令改写内存中的内容,如图所示:

⑥用U命令将内存中的机器指令翻译成汇编指令

可以用U命令将内存中的机器指令翻译成汇编指令,如图所示:

⑦用T命令执行一条机器指令

可以用T命令执行一条机器指令,如图所示:

(A指令的使用方法将在实验任务中展示。)

2、实验任务

(1)使用Debug,将下面的程序段写入内存,逐条执行,观察每条指令执行后CPU中相关寄存器中内容的变化。

 机器码        汇编指令
b8 20 4e    mov ax,4E20H
05 16 14    add ax,1416H
bb 00 20    mov bx,2000H
01 d8        add ax,bx
89 c3        mov bx,ax
01 d8        add ax,bx
b8 1a 00    mov ax,001AH
bb 26 00    mov bx,0026H
00 d8        add al,bl
00 dc        add ah,bl
00 c7        add bh,al
b4 00        mov ah,0
00 d8        add al,bl
04 9c        add al,9CH

提示,可用E命令和A命令以两种方式将指令写入内存。注意用T命令时,CS:IP的指向。

首先用R命令查看当前寄存器内容,如图所示:

分别用E命令和A命令以两种方式将指令写入内存

Ⅰ E命令

Ⅱ A命令

反汇编结果:

执行代码前需修改CS:IP,以指向指定的内存段,并用R命令查询是否修改成功:

用T命令执行

由执行过程可以看出,IP的增加值与对应的代码的机器码长度有关。

(2)将下面3条指令写入从2000:0开始的内存单元中,利用这3条指令计算2的8次方。

mov ax,1
add ax,ax
jmp 2000:0003

输入3条指令,并且修改CS:IP,用R命令检查:

AX作为累加单元,初始值为0001。JMP为立即数,表示将立即数转移到IP中,执行结果中IP的值在不断改变,在执行过程中充当循环的作用,题目所求2的8次方,即使mov ax,ax循环8次,结果如下:

图中标识处即为求得的2的8次方结果(16进制表示)

(3)查看内存中的内容

PC机主板上的ROM中写有一个生产日期,在内存FFF00H~FFFFFH的某几个单元中,请找到这个生产日期并试图改变它。

由结果可得,生产日期为01/01/92,下面试图改变这个日期:

由结果可得,生产日期在只读的地址空间,故只能读取而不能写入,也就不能改变它。

(4)向内存从B8100H开始的单元中填写数据,如:

-e B810:000 01 01 02 02 03 03 04 04

请读者先填写不同的数据,观察产生的现象;再改变填写的地址,观察产生的现象。

有图片欸!!!!!

改变填写的数据和填写的地址:

结果显示,B8100H在显存地址空间,故在B8100H开始的单元中填写数据会被读取并解析为对应的屏幕信息并显示。

(二)汇编语言(王爽第4版)实验2 用机器指令和汇编指令编程

1、实验任务

(1)使用Debug,将下面的程序段写入内存,逐条执行,根据指令执行后的实际运行情况填空。

mov ax,ffff
mov ds,ax

mov ax,2200
mov ss,ax

mov sp,0100

mov ax,[0]     ;ax=_____
add ax,[2]     ;ax=_____
mov bx,[4]     ;bx=_____
add bx,[6]     ;bx=_____

push ax        ;sp=_____ ; 修改的内存单元的地址是_____内容为_____
push bx        ;sp=_____ ; 修改的内存单元的地址是_____内容为_____
pop ax         ;sp=_____ ; ax=_____
pop bx         ;sp=_____ ; bx=_____

push [4]       ;sp=_____ ; 修改的内存单元的地址是_____内容为_____
push [6]       ;sp=_____ ; 修改的内存单元的地址是_____内容为_____

为了便于验证实验结果,对「2. 实验任务」的(1)做如下两点调整:
① 在使用 a 命令输入指令调试之前,先使用 e 命令将内存单元 0022:0 ~0022:7连续 8 个字节数据修改为 50H, 51H, 52H, 53H, 54H, 55H, 56H, 57H
② 将 P74 实验任务(1)中第1行的 mov ax, ffff 改为 mov ax, 0022 

过程如下所示:

结果如下图所示:

在这里执行mov ss,ax时,mov sp,0100也跟着执行了

执行push时,先sp-2,再将数据放入到栈中

执行pop时,先取出数据到寄存器,然后sp+2

需要特别注意的是,ss:sp始终指向栈顶元素

 故需填内容为:

mov ax,[0]     ;ax=5150H
add ax,[2]     ;ax=A4A2H
mov bx,[4]     ;bx=5554H
add bx,[6]     ;bx=ACAAH

push ax        ;sp=00FEH ; 修改的内存单元的地址是2200:00FE内容为A4A2H
push bx        ;sp=00FCH ; 修改的内存单元的地址是2200:00FC内容为ACAAH
pop ax         ;sp=PPFEH ; ax=ACAAH
pop bx         ;sp=00FCH ; bx=A4A2H

push [4]       ;sp=00FEH ; 修改的内存单元的地址是2200:00FE内容为5554H
push [6]       ;sp=00FCH ; 修改的内存单元的地址是2200:00FC内容为5756H

(2)仔细观察图3.19中的实验过程,然后分析:为什么2000:0~2000:f中的内容会发生改变?

由此可以看出:没有数据可以作为栈用

当把2000:0~2000:f作为栈的时候,系统会把寄存器的一些数据暂存在栈中,比如数据CS:IP先后得到暂存。

进一步执行代码后发现,栈还可以暂存AX寄存器的数据,对应标志寄存器。

其中,前3行汇编指令的功能分别为:

第1行:为AX寄存器赋值2000;第2行:初始化栈基地址为ax中的值;第3行:初始化栈顶偏移地址为10。

需要特别注意的是:mov ss,ax和mov sp,0100先后一起执行。

基于单步调试观察到的变化,且经查询可得,DOS下系统只有一个栈,当外部操作未设置栈的时候,系统已经有了一个栈在保存相关数据;当外部操作设置栈的时候,暂存的数据就被保存在新设置的栈中,也即push前,系统已经在暂存数据了,但由于是暂存的,故其内容会发生改变。

三、实验总结

1、实验1总结:实验中印象最深刻的是Jmp立即数,其表示立即数转移到ip中,短短一条指令却可以实现指令的循环和跳跃执行。以及!才发现高级语言是多么的方便和简单!!!!QAQ

2、实验2总结:实验中发现,类似mov sp,10H这样的指令,可以对栈多很多的动作(有点神奇)。

同时,经查询得到,DOS下,栈只有一个,其可以暂存很多数据,如CS:IP,AX,标志寄存器,但是是否暂存更多的数据仍需要进一步的学习与探索!!!