学汇编,记笔记(二)《汇编语言》王爽著——Intel8086寄存器的内存访问

185 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

学习教材:《汇编语言(第4版)》王爽著 此笔记是书中内容+自我总结,方便查阅和复习 请支持原著

一、内存中字的存储

CPU中一个字寄存在一个十六位寄存器中。其中:高八位存放高位字节,低八位存放低位字节

字单元由两个连续单元组成,起始地址为N的字单元称为N地址字单元,N地址单元由地址为N和N+1两个单元构成

在这里插入图片描述

  • 0地址单元中存放的字节型数据是11H
  • 0地址字单元中存放的字型数据是2211H(注意顺序)(地址单元地址字单元
  • 1地址字单元中存放的字型数据是3322H

二、内存地址寄存器

内存地址由段地址和偏移地址组成,DS寄存器用来存放段地址偏移地址由[...]表示

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

指令执行时,CPU自动取DS内的数据作为段地址,最终将10000H(1000:0)中的数据送入了al

由上所示,CPU不支持将数据直接送入DS寄存器,需要将地址数据先送入一个普通寄存器(即上方的bx),再将普通寄存器中的地址数据传入DS段寄存器

实验:写出下面的命令执行后内存中的值

在这里插入图片描述

mov ax,1000H  //ax=1000H
mov ds,ax  	  //ds=1000H
mov ax,2C34H  //ax=2C34H
mov [0],ax    //&10000H=2CH, &10001H=34H
mov bx,[0]    //bx=2C34
sub bx,[2]    //bx=2C34H-1122H=1B12H
mov [2],bx    //&10002H=12H, &10003H=1BH

最终10000H-10003H为:34、2C、12、1B

三、mov、sub、add指令

mov支持的操作

  • mov 寄存器,数据
  • mov 寄存器,寄存器
  • mov 寄存器,段寄存器
  • mov 寄存器,内存单元
  • mov 内存单元,寄存器
  • mov 内存单元,段寄存器
  • mov 段寄存器,内存单元
  • mov 段寄存器,寄存器

用mov指令访问内存单元可以只给出偏移地址,段地址默认存放在ds寄存器中

add、sub支持的操作

  • add(sub) 寄存器,数据
  • add(sub) 寄存器,寄存器
  • add(sub) 寄存器,内存单元
  • add(sub) 内存单元,寄存器

寄存器的清零

要清零寄存器,可以用mov置零或是sub自减。区别在于sub ax,ax的机器码是二字节,而mov ax,0的机器码是三字节

四、栈

栈有两种基本操作:入栈和出栈,操作规则为LIFO(Last In First Out,后进先出),且这两种操作都是以字为单位进行,对应指令为push与pop。

首先入栈的存入最高位字单元 在这里插入图片描述

五、栈地址寄存器

当我们将某一段内存当作栈来使用时,CPU是如何知道这段地址是栈呢?

8086CPU中有两个寄存器段寄存器SS和寄存器SP,SS存有栈顶段地址,SP存有偏移地址。任意时刻,SS:SP指向栈顶元素 在这里插入图片描述 如同DS,SS也不支持直接传入数据,需要普通寄存器作为中转

空栈时

若栈空,SP会指向栈最高地址单元的下一个地址

在这里插入图片描述

六、push、pop指令

支持的操作

注意:以字为单元

  • push(pop) 寄存器
  • push(pop) 段寄存器
  • push(pop) 内存单元

例如:

mov ax,1000H
mov ds,ax
push [0]
pop [2]

push ax的执行

  1. SP-=2,SS:SP指向当前栈顶前面的单元,成为新栈顶
  2. 将ax的内容送入新栈顶

pop ax的执行

  1. 将SS:SP指向的数据送入ax,即当前栈顶值送入ax
  2. SP+=2,SS:SP指向当前栈顶下面的单元,成为新栈顶 在这里插入图片描述

七、栈顶越界问题

对满栈进行入栈、对空栈进行出栈都会导致栈顶超出了栈空间,引起栈顶超界问题

栈顶超界是危险的,可能会导致栈外的重要数据、代码被以外改写,引发不可预料的错误

8086CPU不保证对栈的操作不会引起越界,它只知道当前栈顶的位置,而不知道栈的空间大小。因此操作栈时要人工考虑栈顶越界问题

实验:编程

  1. 将10000H~1000FH作为空栈;

  2. 设置AX=001AH,BX=001BH,先后入栈;

  3. 将AX,BX清零;

  4. 从栈中恢复AX,BX的数据;

    mov ax,1000H
    mov ss,ax
    mov sp,0010H  //注意空栈的栈顶指针
    
    mov ax,001AH
    mov bx,001BH	
    push ax
    push bx
    
    sub ax,ax
    sub bx,bx
    
    pop bx
    pop ax
    

八、栈段

我们可以将长度为N(N<=64KB)的一组地址连续,起始地址是16的倍数的内存单元当作一个栈空间使用,从而定义了一个栈段

一段内存可以既是代码存储空间,又可以是数据存储空间,还可以是栈空间,也可以什么都不是。关键在于CPU中寄存器的设置,即CS、IP、SS、SP、DS的设置。是因为先有了寄存器设置,才有了那段内存的属性

为什么一个栈段最大是64KB?

由于对栈的操作是基于更改SP完成,而SP是一个十六位寄存器,因此只能到FFFFH,若继续移动那么栈就会循环到栈最低地址从而引发覆盖