Debug可以查看COU各种寄存器中的内容,内存的情况,并且在机器指令级跟踪程序的运行
一、命令
用R命令查看,改变CPU寄存器的内容
用D命令查看内存中的内容
用E命令改变内存中的值
用U命令将内存中的机器指令翻译为汇编指令
用A命令以汇编指令的格式在内存中写入机器指令
用T命令执行机器指令
1.R命令
R命令查看,改变CPU寄存器的内容
R 寄存器名 改变指定寄存器内容
2.D命令
D命令查看内D存中的内容
D —— 列出预设地址内存处的128个字节的内容
D 段地址:偏移地址 —— 列出内存中指定地址处的内容
D 段地址:偏移地址 结尾偏移 —— 列出内存中指定地址范围内的内容
3.E命令
E命令改变内存中的值
1.
E 段地址:偏移地址 数据1 数据2....
改变指定内存的值
2.
E 段地址:偏移地址
逐个询问式修改
空格-接受,继续
回车-结束
4.U命令
命令将内存中的机器指令翻译为汇编指令
E 地址 数据——写入
D 地址 —— 查看
U地址 —— 查看代码
5.A命令
以汇编指令的格式在内存中写入机器指令
A 地址——写入汇编指令 MOV AX,0123
D 地址—— 查看数据
U 地址——查看代码
6.T命令
执行机器指令
T ——执行CS:IP处的指令
7.Q命令
退出Debug
二、CS ,IP与代码段
cpu将内存中CS:IP指向的内容当做指令执行
1.8086CPU工作流程
1.从CS:IP指向的内存单元读取指令,读取到的指令进入指令缓冲区
2.IP=IP+所读取的指令的长度,从而指向下一条指令
3.执行指令,转到步骤1,重复这个过程
内存中有一串数据,究竟是将这一串数据当做一般数据,还是用作指令?
CPU将CS:IP指向的内存单元中的内容看做指令
三、jmp指令
CPU执行何处的指令由CS:IP来决定
所以可以改变CS,IP中的内容,来控制CPU要执行的目标指令
所以需要用到jmp指令
注意:对通用寄存器之外的寄存器,8086CPU是不能使用mov指令来修改其他寄存器的内容的
1.同时修改CS、IP的内容
jmp 段地址:偏移地址
2.只修改IP的内容
jmp 某一个合法的寄存器
eg: jmp ax 类似于 mov IP AX
功能:用寄存器中的值修改IP中的值
四、内存中字的存储
8086是16位CPU:意味着8086的字长是16bit
一个字可以存在一个16位寄存器中
这个字的高位字节存在这个寄存器的高8位寄存器(AH)
这个字的低位字节存在这个寄存器的低8位寄存器(AL)
16位的字需要2个连续字节存储,低位字节存放在低地址单元,高位字节存放在高地址单元
eg. 4e20H存放在0,1两个单元,0012H存放在2,3两个单元
0存放20H,1存放4eH,2存放12H,3存放00H
1.字单元
由两个地址连续的内存单元组成,存放一个字型数据(16位)
字型数据(两个字节)和字节型数据(一个字节)不同
五、DS和[address]实现字的传送
要解决的问题:CPU从内存单元中要读取数据?
要求:CPU要读取一个内存单元的时候,必须先给出这个内存单元的地址
而内存地址由段地址和偏移地址组成(段地址:偏移地址)
解决方法:
用DS寄存器存放要访问的数据的段地址
偏移地址用[]形式直接给出
eg:
mov bx 1000H; mov ds bx; mov [0] al; //将al中的数据写到10000H中(1000:0) mov al,[0]; //将10000H中的数据写入到al寄存器中
不能写成:
mov ds 1000H
因为8086cpu不支持将数据直接写入到段寄存器中(硬件设计的问题)
只能是:数据——》通用寄存器——》段寄存器
六、DS与数据段
对于8086PC机,可以根据需要将一组内存单元定义为一个段。
物理地址=段地址×16+偏移地址
将一组长度为N (N≤64K )、地址连续、起始地址为16的倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段。
1.处理方法
用DS存放数据段的段地址
用相关汇编指令访问数据段中的具体单元(mov,add,sub),单元地址由[address]给出
2.将内存单元定义为段
将123B0H~123BAH的内存单元定义为数据段
累加数据段中的前3个单元中的数据
mov ax,123BH; mov ds,ax; mov al,0;//将低位寄存器内容全部初始化为0 add al,[0]; add al [1]; add al [2];
累加数据段中的前3个字型数据
mov ax,123BH; mov ds,ax; mov al,0;//将低位寄存器内容全部初始化为0 add al,[0]; add al [2]; add al [4];
3.mov指令形式
//mov 寄存器,数据 mov ax,8; //mov 寄存器,寄存器 mov ax,bx; //mov 寄存器,内存单元 mov ax,[0]; //mov 内存单元,寄存器 mov [0],ax; //mov 段寄存器,寄存器 mov ds,ax; //mov 寄存器,段寄存器 mov ax,ds; //mov 段寄存器,内存单元 mov ds,[0]; //mov 内存单元,段寄存器 mov ds,[0];
注意:
1.不能直接把数据mov到段寄存器中
4.add形式
//add 寄存器,数据 add ax,8; //add 寄存器,寄存器 add ax,bx; //add 寄存器,内存单元 add ax,[0]; //add 内存单元,寄存器 add [0],ax;
注意:
1.两个内存单元不能直接add
2.段寄存器不能使用add
5.sub指令
//sub 寄存器,数据 sub ax,8; //sub 寄存器,寄存器 sub ax,bx; //sub 寄存器,内存单元 sub ax,[0]; //sub 内存单元,寄存器 sub [0],ax;
6.总结
(1)字在内存中存储时,要用两个地址连续的内存单元来存放,字的 低位字节存放在低地址单元中,高位字节存放再高地址单元中。
(2 )用mov指令要访问内存单元,可以在mov指令中只给出单元的偏 移地址,此时,段地址默认在DS寄存器中。
( 3 ) [address]表示一个偏移地址为address的内存单元。
(4)在内存和寄存器之间传送字型数据时,高地址单元和高8位寄存器、 低地址单元和低8位寄存器相对应。
( 5 ) mov、add、sub是具有两个操作对象的指令,访问内存中的数据段
(对照:jmp是具有一个操作对象的指令,对应内存中的代码段)。
(6 )可以根据自己的推测,在Debug中实验指令的新格式。
七、栈与栈操作的实现
1.概念
CPU提供的栈机制
1.现今的CPU中都有栈的设计。
2.8086CPU提供相关的指令,支持用栈的方式访问内存空间
3.基于8086CPU的编程,可以将一段内存当作栈来使用。
PUSH(入栈)和POP(出栈)指令
push ax :将ax中的数据送入栈中
pop ax ∶从栈顶中取出数据送入ax
(以字为单位对栈进行操作)
问题∶ 1、CPU如何知道一段内存空间被当作栈使用?
2、执行push和pop的时候,如何知道哪个单元是栈顶单元?
回答:
8086CPU中,有两个与栈相关的寄存器:
1.栈段寄存器SS——存放栈顶的段地址
2.栈顶指针寄存器SP -存放栈顶的偏移地址
任意时刻,SS:SP指向栈顶元素。
2.使用
mov ax,1000H; mov ss,ax; mov sp,0010H;//此时 ss:sp——指向栈顶位置1000:0010 mov ax,001AH; mov bx,001BH; push ax; push bx; pop ax; pop bx;
push——sp=sp-2
pop——sp=sp+2
注意:
使用pop和push都有越界问题,因为使用的是汇编语言这种低级语言,所以不能自动检查,只能程序员自己注意是否内存越界
3.总结
push、pop 实质上就是一种内存传送指令,可以在寄存器和内存之间传送数据,与mov指令不同的是,push和pop指令访问的内存单元的地址不是在指令中给出的,而是由SS:SP指出的。
执行push和pop指令时,SP中的内容自动改变。
8086CPU提供的栈操作机制︰
在SS,SP中存放栈顶的段地址和偏移地址,入栈和出栈指令根据SS:SP指示的地址,按照栈的方式访问内存单元。
push指令的执行步骤:
1.SP=SP-2;
2.向SS:SP指向的字单元中送入数据。
pop指令的执行步骤
1.从SS:SP指向的字单元中读取数据;
2.SP=SP-2。
八、关于段的总结
物理地址=段地址×16+偏移地址
1.定义段
编程时,可以根据需要将一组内存单元定义为一个段。
可以将起始地址为16的倍数,长度为N (N ≤64K )的一组地址连续的内存单元,定义为一个段。
将一段内存定义为一个段,用一个段地址指示段,用偏移地址访问段内的单元――在程序中可以完全由程序员安排。
2.三种数据段
数据段
1.将段地址放在DS中
2.用mov、add、sub等访问内存单元的指令时,CPu将我们定义的数据段中的内容当作数据段来访问;
代码段
1.将段地址放在CS中,将段中第一条指令的偏移地址放在lP中
2.CPU将执行我们定义的代码段中的指令;
栈段
1.将段地址放在ss中,将栈顶单元的偏移地置放在SP中
2.CPU在需要进行栈操作(push、pop)时,就将我们定义的栈段当作栈空间来用。