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

实验2 用机器指令和汇编指令编程

1.预备知识:Debug的使用

【1】合理利用在debug中cs、ds、ss、es这4个段寄存器。简化debug命令格式。

【2】注意在执行t命令时,如遇到初始化栈结构的指令,为了避免sp指针设置出问题,mov ss,ax和mov sp,10一个执行了。这个涉及到了t命令的单步中断问题,下面章节有介绍。

2.实验任务

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

mov ax, ffff

mov ds,ax

 

mov ax,2200

mov ss,ax

 

mov sp,0100

 

mov ax,[0]

add ax,[2]

mov bx,[4]

add bx,[6]

 

push ax

push bx

pop ax

pop bx

 

push [4]

push [6]

程序分析:

【1】我采用的系统是XP sp3的系统自带的debug。不同的系统,可能产生的结果不同,在于体会它的原理。你看你自己debug的显示结果。

debug程序运行后执行r命令查看状态如下:

-r

AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000

DS=0B04  ES=0B04  SS=0B04  CS=0B04  IP=0100   NV UP EI PL NZ NA PO NC

【2】我们使用d命令显示下:内存情况

-d ffff:0

FFFF:0000  EA 5B E0 00 F0 31 30 2F-30 35 2F 30 37 00 FC AD   .[...10/05/07...

FFFF:0010  34 12 00 00 00 00 00 00-00 00 00 00 00 00 00 00   4...............

……

我们发现貌似是主板的BIOS信息

我们再查看下2200H段内存信息

-d 2200:0

2200:0000  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

2200:0010  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

2200:0020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

……

发现是未开发的处女地。内存单元都是00H

【3】强调,在debug中,汇编指令操作数如果是立即数,它们都是16进制的,如2200、FFFF等,你不需要标明H

【4】将这个代码块写在哪?看看ip=100,cs值不动了,直接从cs:100处将这个代码段写入内存吧。

       使用a命令。

-a cs:100

0B04:0100 mov ax,ffff

0B04:0103 mov ds,ax

0B04:0105 mov ax,2200

0B04:0108 mov ss,ax

0B04:010A mov sp,0100

0B04:010D mov ax,[0]

0B04:0110 add ax,[2]

0B04:0114 mov bx,[4]

0B04:0118 add bx,[6]

0B04:011C push ax

0B04:011D push bx

0B04:011E pop ax

0B04:011F pop bx

0B04:0120 push [4]

0B04:0124 push [6]

【5】我们逐步分析:

mov ax, ffff

mov ds,ax

代码含义:首先将ds指向了FFFF段内存,也就是数据段是ffffH:00开始的内存单元了。

mov ax,2200

mov ss,ax

 

mov sp,0100

代码含义:人为建立一个栈结构,ss指向2200H段的内存,初始化栈顶指针是100H,ss:sp指向栈底后面第一个单元(目前栈结构是空);也就是说这个栈结构栈底后面第一个单元地址是2200:100H(物理地址:22100H);这个栈容量是多少?100H个字节=256个字节=128个字单元。

 

执行完答案如下:

mov ax, ffff

mov ds,ax

 

mov ax,2200

mov ss,ax

 

mov sp,0100

;参看自己机器上的ds段内存,我的上面都显示出来了。

mov ax,[0]        ;ax=5BEA

;ax=ax+[2]=5BEA+00E0=5CCA

add ax,[2]        ;ax=5CCA

mov bx,[4]        ;bx=31F0

;bx=bx+[6]=31F0+2F30=6120

add bx,[6]        ;bx=6120

;将ax=5CCA压栈;sp=sp-2=100H-2,此时栈中就一个元素(5CCA)

push ax           ;sp=FEH     ;修改的内存单元的地址是    2200:FE到FF  内容为:CA 5C

;将bx=6120压栈;sp=sp-2=FEH-2=FCH,此时栈中2个元素了。

push bx           ;sp=FCH     ;修改的内存单元的地址是    2200:FC到FD  内容为:20 61

;将栈顶元素(6120)弹出送入ax中,首先ax=6120,然后sp=sp+2=FCH+2=FEH

pop ax            ;sp=FEH     ;ax=6120   

;将栈顶元素(5CCA)弹出送入bx中,首先bx=5CCA,然后sp=sp+2=FEH+2=00H,栈空。

pop bx            ;sp=00H     ;bx=5CCA

;将内存单元[4]和[6]压栈,

push [4]          ;sp=FEH     ;修改的内存单元的地址是    2200:FE到FF    内容为:F0 31

push [6]          ;sp=FCH     ;修改的内存单元的地址是    2200:FC到FD    内容为:30 2F

程序理解:

【1】以上是我们人为的创建了一个栈的结构,这个栈最大使用空间是256字节(100H),栈是个逻辑结构,它的实质就是一段连续的内存空间,只不过访问内存的方式不像我们原来的CPU寻址方式,使用push和pop访问。

【2】栈使用的实际空间是随着sp指针的指向而发生改变的,它和最大使用空间是有区别的。栈空,sp=100H,此时栈未使用任何内存空间,栈满,sp=0,它使用了从100H~0H(偏移地址)的最大内存空间。

【3】栈操作的对象基本单位是字单元(2个字节)。对应的内存就是2个内存单元。

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

       可能要再做些实验才能发现其中的规律。如果你在这里就正确回答了这个问题,那么要恭喜你,因为你有很好的悟性。大多数的学习者对这个问题还是比较迷惑的,不过不要紧,因为随着课程的进行,这个问题的答案将逐渐变得显而易见。

分析:   

       观察3.19图,我们在2000H内存段创建了一个栈结构,最大空间是10H,ss:sp指向了栈顶2000:10H(栈空)

       给ax赋值后压栈。

分析:

       初始没有执行这段代码时,我们使用d命令观察2000:00内存,都是00,怎么创建栈结构指向这段内存时,我们发现有些数据了。这些数据是什么?

       我们发现这里面有cs值、ip值、ax值(这个容易看出来),还有bp值(00 00),还有flag的值(这个我用肉眼是看不出来了。呵呵,就是那个一排英文字符)。

       为什么,在讲内中断这章时,你就明白了。t命令实际是引发了单步中断,执行中断例程时,CPU会将一些中断例程使用的的寄存器变量自动压栈到栈中,此例中就包括了上述的寄存器变量的值。

       我们可以不必理会这些寄存器的变量,我们只关心sp就可以了。有它指示,我们就可以对栈进行操作了。而此时的sp是正确的,

       注意:这个栈和我们创建的栈是同一个栈结构(为什么,ss=2000H了),由于t命令必须保存寄存器变量的值(这个是中断程序定义的。)它也占用一定的空间。可能我们定义的栈空间比较小;频繁的使用push指令,为了避免栈顶超界,我们尽量使栈空间大些,就像此程序,设定栈空间是100H。

 

 

posted @ 2017-05-21 08:36  筑基2017  阅读(1659)  评论(0编辑  收藏  举报