x86汇编语言之段寄存器和栈空间

381 阅读5分钟

「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」。

段寄存器

  1. 数据和指令的区别

内存中存放的数据都是十六进制的数据,如果这些十六进制数据被标记为数据,那么cpu在读取的时候,读到多少就是多少,如果被标记为了指令,那么cpu会将这些十六进制转成指令进行执行

cpu只是个无情的计算机器,它无法自动区分数据和指令,标记需要我们告诉cpu

那么 如何给数据进行标记呢?

  1. 段寄存器的种类
DS---->data segment
SS---->stack segment 
CS---->code segement 
ES---->extra segement

都是用于存放段地址的

实际物理地址=段地址*16:偏移地址 10*10=100  
71001	  =	0710*16:0001

DS寄存器用于存放数据的段地址,那么数据所对应的偏移地址可以使用bx寄存器进行存放,使用DS寄存操作的内存数据都被当成是纯数据,里面存的是什么,读出来的就是什么

mov ax,3000H  ;这行代码会转成16进制的数据存放到内存中 这些数据所对应的段地址默认放在ds寄存器中 ,使用ds进行读取的时候 读取的是该指令对应的16进制数据, 而不是被还原成了指令进行执行

CS寄存器用于存放指令所在的段地址,IP寄存器存放的是当前正在执行的指令所对应的偏移地址,所有使用CS:IP进行操作的内存数据都被当成是指令对待,读取的时候会将16进制数据转成对应的指令并执行

mov bx,3333H ;假如这条这条指令数据所对应的物理地址为0710:0000
mov ax,2000H ;假如这条这条指令数据所对应的物理地址为0710:0003


;如果我想跳过第一条指令 直接执行第二条指令 那么直接修改CS:IP的值为0710:0003即可

SS寄存器用于存放栈空间对应的段地址,所有被SS操作的内存空间都被当成栈空间进行对待,你想让哪部分内存空间当作栈空间,完全取决于开发者,sp寄存器存放栈空间偏移量,ss和sp配合使用

mov ax,0710H
mov ss,ax 
mov sp,20 ;将0710:0000~0710:0014H 这20个字节的内存空间定义为栈空间

ES寄存器一般用于DS的替补,DS被占用无法使用时,临时使用ES替代,用法和DS一致

栈空间的操作

栈段里面存放也是数据和数据段无异,只不过数据排列的方式不一样,正常的排列方式是数据从低地址往高地址进行偏移存放,读取数据也是从低到高,而栈则是写入数据从高到低进行偏移,读取数据从低地址到高地址

由于这个特性,所以我们在定义一块空间作为栈空间使用时,都会先往高地址偏移一段空间

栈存储特点:

  • 一次读写两个字节的数据

  • 数据高地址往低地址逆序偏移存放

  1. 栈空间的声明

    前面提到过,使用ss寄存器进行标记的空间为栈空间

    data segment
    	db 0,0,0,0,0,0,0,0 ;定义数据相当于是开辟了一块未标记内存空间,这块空间可以当作是数据空间也可以栈或者指令空间,却决于该段地址是由哪个段寄存器进行管理的
    data ends
    
    code segment
    	start:
    		mov ax,data
    		mov ss,ax ;该空间被ss指向,因此被当作是栈空间 如果是被CS指向则被当成指令空间,里面存放的数据都会被当成指令进行执行
    		mov sp,8
    code ends
    end start
    
  2. 往栈空间中写入数据

使用push指令

data segment
	db 0,0,0,0,0,0,0,0 
data ends

code segment
	start:
		mov ax,data
		mov ss,ax 
		mov sp,8
		
		mov ax,2000H
		push ax  ;一次写入两个字节的数据,如果使用al编译报错
code ends
end start
  1. 从栈空间读取数据

    使用pop指令

    data segment
    	db 0,0,0,0,0,0,0,0 
    data ends
    
    code segment
    	start:
    		mov ax,data
    		mov ss,ax 
    		mov sp,8
    		
    		mov ax,2000H
    		push ax
    		
    		pop bx  ;一次读取两个字节的数据,如果使用bl编译报错
    code ends
    end start
    

    思考:栈空间和数据段空间,里面存放的都是数据,那么是否可以使用SS来存放数据段的段地址呢,答案是可以的, 当SS充当数据段的时候,读写操作和DS一样,SS:[N],如果充当栈段的时候,读写操作时候时候pop和push,

    由于pop和push默认以SS寄存器中的数据当做栈段地址,因此不能使用其他段寄存器充当栈段寄存器