汇编ds和ss寄存器

一、DS寄存器
8086CPU寄存器都是16位的,数据类型有一下两种:
字节型数据
字型数据
16位寄存器存储一个字,而内存中需两个连续字节单元存储;任何两个连续的内存单元可以看作两个字节单元或一个字单元
cpu通过cs:ip寄存器获取下条指令地址。而需要获取数据就需要通过ds寄存器,ds段地址寄存器存放要访问数据的段地址
2000:0000 11223344//2000:0000设置初始值
mov bx,2000
mov ds,bx//设置ds段地址寄存器值为2000
mov al,[0]
mov cx,[1]
以上指令将2000:0000地址单元字节型数据值读取到al寄存器,将2000:0001地址单元字型数据读到cx寄存器。[]表示内存单元,其中0表示偏移地址,CPU 会自动读取ds的数据作为内存单元的段地址。最终的寄存器值为:
BX=2000
DS=2000
AX=0011
CX=3322
同样,DS和CS等段地址寄存器都是相同的,不支持将数据直接送进段地址寄存器中,要通过其他寄存器中转,这属于硬件设计问题。
当然也可以将al、ax存向[n]//各种合理组合
mov [0],al
mov [2],ax
add ax,[0]
add [0],ax
sub al,[0]//相减的结果保存到al中
sub [0],ah//相减的结果保存到ds:[0]
以下指令是不合理的:
mov ds,1000
add ds,ax
sub ds,ax

内存中数据与命令完全没有区别;而寄存器中数据和命令是有区别的,不同寄存器保存的是不同类型数据的地址//CS保存指令数据段地址,DS保存操作数段地址;而CPU负责读取CS:IP确定下条指令存放的地址,读取DS得知将要处理的数据的段地址,根据指令中偏移地址找到具体的数据。所以说,汇编程序通过CPU读取寄存器寻找指令与数据,进行一系列的操作。
二、ss/sp栈段寄存器
在高级语言中,都使用过栈这种数据结构,在汇编这种古老的语言中,栈当然也是存在的。那么如何使用寄存器描述一个栈空间?就要用到ss和sp寄存器。对8086汇编来说,一次入栈/出栈的字节数都是2字节即1字。
push指令:
1》SP-2
2》将字型数据存放到SS:SP地址中
pop指令:
1》将SS:SP地址的字型数据取出来
2》SP+2
上面步骤像是C中我们入栈前先移动栈顶指针,再入栈。出栈时先取出数据,再将栈顶指针向栈底移动//属于“满栈” 先移动Top再压栈
指令使用法则:
push 16bit寄存器/push DS:[n] :
寄存器可以为ax\bx\cx\dx\ds\es\ss\sp…,8位寄存器不可以//SP-2,从指定寄存器/DS:[n]读取数据入栈
pop 16bit寄存器/pop DS:[n] //从栈中取出数据放到寄存器/DS:[n]地址中,SP+2
//在debug中,ds:需要省略,只用一个[n],CPU自动会从DS中读取栈段地址。可以从寄存器或DS:[]地址中读取数据入栈,但是不能“push FFFF”,出栈亦然
注意:
任意时刻,SS:SP指向栈顶元素//SS:SP就类似一个Top指针,所以说栈在哪里是由SS:SP决定的,但是栈大小没有严格界限,当SP-2<0时,又会从FFFF开始减,但是不保证其权限,可能越界错误//不会自动判断栈满栈空。//而栈的越界问题需要程序员自己注意,比C更自由,但更不安全
mov ax,2000
mov ss,ax
mov sp,10//IP寄存器不能直接用值修改,但sp寄存器可以

//就是指定栈底地址为2000:10,此时ss:sp=2000:0010
mov ax,1234
mov bx,5678
push ax //sp-2=000E,2000:E与2000:F分别存放34和12
push bx //sp-2=000c,2000:c与2000:D分别存放78和56
pop cx
pop dx
出栈是其逆过程,先出值到寄存器中,再移动栈顶指针(修改ss:sp寄存器)
明白了CS、DS、SS寄存器,为数据段text、代码段code、栈段stack总结:
数据段:存放数据的段,段地址在DS中
代码段:存放代码的段,段地址在CS中
栈段:存放临时性数据的并且由SS:SP维护的段,段地址在S中
三、DS、SS、SP寄存器的混合使用
将10000H~1001F中的8个字,逆序复制到20000H中,如何做:
法一:
从ds:[]入栈,ds:[]是源(10000H~),栈目标(20000H)
mov ax,1000H
mov ds,ax

mov ax,2000H
mov ss,ax
mov sp,10H
//从数据段向栈段复制
push [0]
push [2]
。。。
法二
出栈至ds:[],栈是源,ds:[]是目标
mov ax,2000H
mov ds,ax
设置栈段地址
mov ax,1000H
mov ss,ax
mov sp,0H

pop [E]
pop [C]
。。。
汇编ds和ss寄存器_第1张图片
四、win32
在win32保护模式下,段寄存器(cs、ds、ss、es、fs、gs)指向各自的描述符,那些描述符都指向一个段起始地址(fs除外)。所以在win32编程,不要制定cs、ds、ss等,因为他们都是一样的,可以认为ds=es=ss=…这就是flat的含义,在编程者看来,各个段都是平坦的,一样的,没有区别。
至于数据代码的访问属性,是在pe文件的节里面定义的,pe文件加载的时候,文件从磁盘映射到内存后,会根据节的属性修改对应内存的访问属性。

你可能感兴趣的:(windows)