三、寄存器(内存访问)

3 寄存器(访问内存)

3.1 内存中字的存储

(小端存储原则):高地址存放字型数据的高位,低地址存放字型数据的低位;

请添加图片描述

字单元:存放一个字型数据(16位)的内存单元,有两个连续的内存单元构成,该字单元的起始地址成为N,称该单元位N地址字单元;也可称为由高位字节单元、低位字节单元组成。

3.2 ds段地址寄存器

顾名思义:自动保存段地址的寄存器

三句指令让CPU自己定位段地址:

8086CPU不支持直接把十六进制数传送到ds段寄存器中,只能使用下面指令间接修改。(原因是该CPU硬件设计问题)

mov bx,1000
mov ds,bx
mov al,[0]		//最终将ds:0地址存放的数据放入al寄存器 
//[]说明操作对象是一个内存单元,[0]说明便宜地址是0,它的段地址默认存放在ds寄存器中
//执行该指令时,8086CPU会从ds寄存器中取出段地址

请添加图片描述

3.3 数据段

在内存中的数据,不管是指令还是数据,都是一样的

使用cs:ip可以指定CPU执行指令的地址

使用ds:[address]可以指定CPU拿取数据的地址

假设,将123B0H~123B9H的内存单元定义为数据段,求前三个单元数据的和

mov ax,123B
mov ds,ax
mov al,0
add al,[0]
add al,[1]
add al,[2]

3.4 小结

  1. 字在内存中存储时,用两个连续地址的内存单元来存放(字型数据),字的高位字节放在高位地址,低位字节放在地位地址。(小端存放)
  2. 用mov指令访问内存单元,可以只给出偏移地址,段地址默认在ds寄存器中
  3. [address]表示一个偏移地址为address的内存单元
  4. 在内存和寄存器之间传送数据时,高地址单元和高8位寄存器、低地址和低8位寄存器相对应
  5. mov、add、sub是具有两个操作对象的指令,jmp只有一个操作对象的指令

3.5 栈

栈的规则:LIFO(last in first out):后进先出

CPU都有栈的设计:以栈的方式使用内存(以字节为单位)

push ax	//把寄存器ax的数据入栈操作
pop ax	//把栈顶元素出栈放入寄存器ax中
注意:这两条指令会根据寄存器的位数计算取出数据的字节大小

1)CPU如何知道这段空间是栈空间,如何确定栈顶的位置

8086寄存器中段寄存器ss和寄存器sp,栈顶的段地址存放在SS寄存器中,偏移地址存放在SP寄存器中。

任何时刻,SS:SP指向栈顶元素。push和pop指令执行时,CPU会从这两个寄存器中得到栈顶元素地址。

下面是入栈PUSH操作的内存变化

请添加图片描述

出栈:

  1. 将ss:sp栈顶元素出栈
  2. 再将sp += 出栈元素的大小(byte)

2)设置一个栈

  • 确定起始的地址(例如2000:0)

  • 计算需要栈的大小(10H的倍数最好,例如:10H—>16字节)

  • 栈顶位置ss:sp = 起始地址 + 栈大小(2000:0010H)

请添加图片描述

问题:图中所示(中断机制)

mov ss,ax
mov ss,bx
mov ss,[0]
pop ss等指令都会出现一次执行后面语句也会执行

然后接着执行就好了

3)栈顶越界问题

假设栈的起始位置是2000:0000,(20000H),栈大小10H(16字节),栈顶位置就是ss:sp(2000:0010),所以栈的地址范围就是2000:0000~2000:0010,如果一直入栈操作(出栈操作),当ss:ip位置是2000:0000位置时,说明栈满了,再进行一次入栈操作,就会出现越界问题。

栈越界操作演示:

请添加图片描述

接着一顿操作执行后:我的dos程序被意外终止了,CPU收到一个非法指令,我又在dosbox软件中进行了上述操作却发现,修改成功了,但是改变不了ss:sp越界的事实。
请添加图片描述

严重性:假设越界后,修改了其他地址的内容(可能是指令,可能是数据),都会造成很大的影响。

4)栈的极限大小

请添加图片描述

假设连续入栈操作32768次,最终sp == 0的时候也会导致越界问题。

3.6 栈的作用

call指令调用函数,进入函数,执行完语句后,最后ret退出函数,cpu是怎么知道下一条的指令的。

此时

栈的作用

  • 临时保存数据

    1. 保存了call调用后,ret应该回退的cs:ip位置
    2. 函数调用前使用寄存器ax,push ax,在函数内改变了ax的值,函数执行结束,pop ax。这样就算函数内修改了ax的值,也是在栈中可以取回的。
  • 进行数据交换

    • 使用后进先出的原则
    mov ax,1000
    mov ss,ax
    mov sp,10
    
    mov ax,2233
    mov bx,4455
    push ax
    push bx
    
    pop ax
    pop bx
    

3.7 总结

1)如何让CPU去按照安排去访问内存段呢

  • 数据段:ds段地址寄存器:偏移地址[] 来确定数据段的位置。
mov ax,[0]	//把ds:0位置的数据放入ax寄存器
add ax,[0]
sub ax,[0]
push [0]
pop [0]
...
  • 指令段:使用cs:ip指向的地址作为cpu访问指令段的地址

  • 栈段:通过改变ss:sp栈顶标记的位置去改变栈段的位置

2)内存段的安全

随意向一段未知的内存空间中写入内容是十分危险的行为

安全的内存空间:

0:200~0:2FFH只有256个字节

使用操作系统分配的内存空间(安全的):

  • 系统加载程序时为程序分配内存
  • 程序在运行过程中再去申请内存

段的地址

  • 栈段:通过改变ss:sp栈顶标记的位置去改变栈段的位置

2)内存段的安全

随意向一段未知的内存空间中写入内容是十分危险的行为

安全的内存空间:

0:200~0:2FFH只有256个字节

使用操作系统分配的内存空间(安全的):

  • 系统加载程序时为程序分配内存
  • 程序在运行过程中再去申请内存

猜你喜欢

转载自blog.csdn.net/xiaoxiaoguailou/article/details/121100850
今日推荐