1、 利用 Proteus 和 emu8086 学习寄存器的相关知识
2、 利用 emu8086 简单程序编译仿真过程学习汇编程序与机器码的对应过程,掌握编译完成后的代码的存储原理。
8086CPU的指令执行部件EU有4个16位的寄存器:AX、BX、CX、DX,8个8位的寄存器:AH、AL、BH、BL、CH、CL、DH、DL。
寄存器名称 | 作用 |
---|---|
AX(累加器) | 存放参与运算的数据和结果 |
BX(基址寄存器) | 可以作为数据寄存器,也可以存放内存的逻辑偏移地址 |
CX(数据寄存器) | 可以作为数据寄存器,也可以在串指令和移位指令中计数 |
DX(数据寄存器) | 可以作为数据寄存器,也可以用在乘、除法运算、带符号数的拓展 |
8086CPU的EU中有2个地址指针寄存器SP、BP和2个变址寄存器SI、DI。
寄存器名称 | 作用 |
---|---|
SP(堆栈指针寄存器) | 保存栈顶的偏移地址(隐含的逻辑段地址在堆栈段寄存器中) |
BP(基址指针寄存器) | 保存内存的偏移地址(隐含的逻辑段地址在堆栈段寄存器中) |
SI(源变址寄存器) | 保存内存的偏移地址(隐含的逻辑段地址在数据段寄存器中),也可以存放数据 |
DI(目的变址寄存器) | 保存内存的偏移地址(隐含的逻辑段地址在数据段寄存器中),也可以存放数据 |
8086CPU的总线接口部件(BIU)中有4个16位段寄存器。
寄存器名称 | 作用 |
---|---|
CS(代码段寄存器) | 存放程序代码段起始地址的高16位 |
DS(数据段寄存器) | 存放数据段起始地址的高16位 |
SS(堆栈段寄存器) | 存放堆栈段起始地址的高16位 |
ES(拓展段段寄存器) | 存放拓展数据段起始地址的高16位 |
指令指针寄存器IP存放当前代码段中的偏移地址,它与CS联用,可以形成下一条要取出指令的物理地址。
8086CPU有一个16位标志寄存器(FR),规定了9个标志位,包括6个状态标志(CF、PF、AF、ZF、SF和OF)和3个控制标志(IF、DF和TF)。
打开emu8086软件,新建一个asm文件,输入汇编程序。
下面以从1到100,100个数求和的程序作为例子,展示编译仿真的过程。
汇编程序:
;
;*****************************************************************************
; @file add.asm
; @author Xiaoxiao
; @date 2020-9-23
; @brief 100个数求和(1+2+3+...+100)
; @blog https://blog.csdn.net/weixin_43470383/article/details/108625782
;*****************************************************************************
;
DATA SEGMENT
total DW 0000H
ENDS
STACK SEGMENT
dw 128 dup(0)
ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START:
mov AX, DATA
mov DS, AX
mov ES, AX
MOV CX, 100
MOV AX, 0
MOV BX, 1
add_100:
ADD AX, BX
INC BX
LOOP add_100
MOV TOTAL, AX
JMP $
ENDS
END START
点击 emulate(绿色小箭头),开始仿真,这时会弹出两个窗口:
右边的蓝色区域为汇编原码,左边的蓝色区域为汇编原码编译形成的机器码
第一个窗口中的蓝色区域和第二个窗口中黄色区域是对应的。
load:加载文件。
reload:重新运行代码。
single step:单步运行程序,可以查看每一步运行的结果。
step back:返回上一步运行结果。
run:运行程序,直到结束。
可以看到程序终止于 JMP $,这条指令的意思程序停在这个位置,等待中断。
在机器码的左边可以看到8086的寄存器
上面的程序把1+2+…+100的和存入寄存器AX,BX用来存放加数(1、2…100),CX用来存放计数值,一共100个数相加,所以是100D(64H)。
当执行完 MOV CX, 100 时,CX寄存器变成 00 64(100D = 64H);执行完 MOV AX, 0 时,AX寄存器变成00 00;执行完 MOV BX, 1 时,BX寄存器变成 00 01。
继续运行,循环 add_100 共100次,每一次循环把BX的值加到AX上,然后BX加1,下一次 LOOP 循环的时候CX自动减1。
最终运行结果:AX变成 13 BA (5050D = 13BAH),BX变成 00 65(101D = 65H),CX变成 00 00。
汇编程序中用
段名 SEGEMNT
…
段名 ENDS
来完成段的定义,用
ASSUME 段寄存器名:段名[, …]
来将某段分配给指定段寄存器
例如:
ASSUME CS:CODE, DS:DATA
即为段假设
mov AX, DATA
mov DS, AX
mov ES, AX
即为给除CS以外的其他用到的段的段寄存器赋值
运行结果:
CS:IP 两个寄存器共同指示了 CPU 当前将要读取的指令的地址。
单步执行指令,CPU 就要将偏移地址向下移动,IP地址将发生改变。
在 view -> flags 中可以查看标志寄存器
在 view -> memory 中可以查看代码存储
由于程序起始地址为 0710 : 0000 ,所以将地址改一下,然后update 或者按 enter 键,就可以看到程序运行的存储结果了
将emu8086编译生成的 exe/com/bin 文件,输入到proteus的8086CPU,点击运行,然后在 调试 > 8086 > Registers 中可以查看8086的寄存器。
参考:《微机原理与接口技术》(第4版)电子工业出版社