汇编学习笔记(三)

    技术2024-11-22  19

    汇编入门

    汇编学习笔记(三)8086CPU8086CPU的寻址方法 段寄存器CS和IPDS段寄存器mov, add, sub指令。 SS和SPpush和pop指令栈顶溢出 参考教材

    汇编学习笔记(三)

    8086CPU

    8086CPU是Intel公司1978年设计的16位微处理器芯片,x86架构的鼻祖,一般学习汇编都从8086CPU开始,所以有必要搞清楚8086CPU的相关结构:

    8086是16位机。16位机是指:寄存器的宽度是16位,运算器一次最多可以处理16位数据等。8086的地址总线宽度是20位,所以最大寻址空间为:2^20B = 1MB。8086的数据总线宽度是16位,即一次最大可以传送16bit的数据(2个字节/Byte)。

    8086CPU的寻址方法

    8086的地址总线是20位,但是寄存器是16位,如果地址只是简单的从内部寄存器发出,则只能发出16位地址,无法达到20位,为此,8086运用了两个16位数据的方式来给出20位的地址:

    物理地址(20位) = 地址1(16位)×16 + 地址2(16位)

    说明:

    地址1*16,可以看成地址1左移4位,例如: 地址1 = 1110 0011 1011 1101 地址1 × 16 = 1110 0011 1011 1101 0000

    可以看出16位地址1×16 后就是20位地址了,在加上一个16位地址2还是20位。

    以上中地址1又叫段地址,地址2可以叫做偏移量,所以以上可以写成: 物理地址(20位) = 段地址(16位)×16 + 偏移地址(16位) 一般使用 “段地址:偏移地址”方式来表示上面的等式的右边,所以8086中物理地址可以用“段地址:偏移地址”的方式来表示。执行上述自动运算的电路称为地址加法器。

    段寄存器

    综上,段寄存器就是存放段地址的寄存器,8086CPU有4个段寄存器CS,DS, SS, ES。CPU访问内存单元就由这四个寄存器提供段地址。

    CS和IP

    程序或者说指令都是存放于内存当中的,那么CPU是怎样知道程序和指令的位置并执行的呢?这就靠CS和IP寄存器了。CS是段寄存器,IP是偏移地址,8086CPU中,任意时刻,CPU总是将CS:IP指向的内容当作指令来执行。 8086的工作过程是:

    从CS:IP指向的内存中读取指令,读取的指令进入指令缓冲区。自动执行 IP = IP + 读取的指令的长度,从而让CS:IP指向下一条指令。执行指令,然后转到步骤1。

    8086总是将CS:IP指向的地址作为指令来自动执行,那么怎样修改CS和IP的值让它指向程序呢?

    8086CPU加电启动或复位后,会设置CS=FFFFH, IP = 0000H,所以FFFF0H单元中的指令是8086PC开机后执行的第一条指令。程序中怎样修改CS和IP的值?mov cs, 100? mov指令不能修改CS和IP, 8086提供jmp 段地址:偏移地址方式来修改CS和IP,如jmp 2AC3:1 也可以使用jmp 寄存器来只修改IP的值,如jmp ax。

    DS段寄存器

    CPU读写一个内存地址时,需要定位该地址,这是默认使用的段是DS寄存器,如:

    mov bx, 1000H mov ds, bx mov al, [0]

    1、上面代码将1000:0处的内存数据读入al寄存器,指令mov al, [0]中只给出了数据的偏移地址,CPU自动取ds中的数据为内存单元的段地址。 2、是否可以使用mov ds, 1000H来直接设置段地址?答案是8086CPU不支持直接将数据传送到段寄存器的操作,必须使用寄存器中转。

    mov, add, sub指令。

    mov 指令传送数据:

    mov 寄存器, 数据 如:mov ax, 8 设置ax值为8。mov 寄存器, 寄存器 如:mov ax, bx 将bx中的值复制到ax中。mov 寄存器, 内存地址 如:mov ax, [100] 将ds:100内存处的数据复制到ax中。mov 内存地址, 寄存器 如:mov [100], ax 将ax中的数据复制到内存ds:100处,注意高低位字节顺序。mov 段寄存器, 寄存器 如:mov ds, ax 将ax中的数据复制到ds段寄存器中。mov 寄存器, 段寄存器 如:mov ax, ds 将段寄存器ds中的数据复制到ax中。

    add 指令是加法指令,sub指令是减法指令,用法基本一致:

    add 寄存器, 数据 如:add ax, 8 将ax中的数据和8相加,结果存入axadd 寄存器, 寄存器 如:add ax, bx 将ax和bx数据相加,结果存入axadd 寄存器,内存单元 如:add ax, [0] 将ax和ds:0处数据相加,结果存入axadd 内存单元,寄存器 如:add [0], ax 将ds:0处数据和ax中数据相加,结果存入内存ds:0处。

    SS和SP

    CPU一般都有栈的设计,并提供相关指令以栈的方式来访问内存。8086CPU中对堆栈的描述主要使用SS和SP寄存器,SS:SP始终指向栈顶,SS是段寄存器,SP是偏移地址。

    push和pop指令

    PUSH是入栈指令,POP是出栈指令。如 push ax将ax寄存器中的数据入栈,pop ax将栈顶元素取出放入ax寄存器中。8086CPU中入栈和出栈操作都是以字(word,一个字表示两个字节)为单位进行。 push和pop除了操作通用寄存器外,主要有以下使用方式:

    push/pop 寄存器 ;将一个寄存器数据入栈和出栈。push/pop 段寄存器 ;将一个段寄存器数据入栈和出栈push/pop 内存单元 ; 将内存中的字单元(2Byte,注意高低字节顺序)入栈和出栈。

    前面说了SS:SP总是指向栈顶元素,那么一个PUSH指令操作如push axCPU将做以下过程:

    SP = SP - 2 ; 伪代码,push和pop指令是以字单元为单位,所以是减2mov SS:SP, ax ; 伪代码,将ax数据传送到SS:SP说指向的内存空间

    同理pop axCPU将做的过程如下:

    mov ax, SS:SP ; 伪代码,将当前栈顶字单元数据传送到ax寄存器中。SP = SP + 2 ; 伪代码,弹出栈顶数据,指向新的栈顶元素。

    栈顶溢出

    堆栈通过SS:SP描述,每次push后栈的空间SP将减少2,多次push后,可能导致SP为0,再次push后则栈顶溢出, 8086CPU中SP寄存器为0减2后为FFFE,这样会导致覆盖数据等异常情况,8086CPU不检测栈顶溢出,需要程序编写者自己控制。

    参考教材

    [1]: 王爽老师的 汇编语言(第3版)

    Processed: 0.055, SQL: 9