常用寄存器类型
通用寄存器
AX,BX,CX,DX,这四个寄存器都是16位的
他们也可以拆分为2个8位的寄存器,如AX可以拆分为AH和AL两个8位的寄存器,其它三个也可以如此。
通用寄存器的使用比较简单,如
mov ax, 0x0253,当然也可以将0x0253写成0253H。
该指令是将0253放入ax寄存器中。
mov ax, bx
该指令是将bx寄存器的数据放入ax中。
add ax, 0x0205
该指令是将ax中的数据与0205相加之后放入ax中。
ah和al以及其它的通用寄存器的使用与之类似,要注意的是存放的数据位数要保持一致。
段寄存器
CS,DS,SS,EX。
CS:为代码段寄存器,通常与IP(指令指针寄存器)一同使用,其格式为CS:IP。
其实际的物理地址为CS*16+IP,即CS左移4位,再加上IP,就可以得到实际的物理地址了。
修改CS和IP可以用jmp指令,如
jmp 3:0B16H
其中CS=3,IP=0B16,该指令就可以使CPU从物理地址30+0B16处读取指令。
如果仅想修改IP的值,可以用指令
jmp ax
这样就可以将IP改成ax寄存器里的值,而CS的值保持不变。注意的是这里应该是只能用寄存器来jmp。这里存疑。
DS:为数据段寄存器,DS必须用寄存器的赋给它,如
mov bx, 0x1562
mov ds, bx
这里是将1562先存放到了bx寄存器中,再由bx寄存器mov到ds,而不能直接mov ds, 0x1562
mov al, [0]
该指令是将0内存单元的内容放到al寄存器中。[]表示一个内存单元,[0]中的0表示内存单元的偏移地址,当然也可以将al寄存器中的数据放入第0地址单位内,指令为
mov [0], al
那么
mov ax, 0x1562
mov ds, ax
mov al, [0]
合起来就可以指定要访问的数据的段地址和偏移地址了,其段地址为0x1562,偏移地址为0,段地址存储在ds中。
例子:
mov ax, 1000H ;将1000H放入ax
mov ds, ax ;将ax赋给ds,即这里的段地址被设为1000H
mov ax, [0] ;将第0内存单元的数据赋给ax,这里的地址为10000H+0,所以ax的值为1123
mov bx, [2] ;将第2内存单元的数据赋给bx,地址不变,bx的值为6622
mov cx, [1] ;将第1内存单元的数据赋给cx,地址不变,cs的值为2211
add bx, [1] ;将第1内存单元的数据加上bx的值,再放入bx,则bx=2211+6622=8833
add cx, [2] ;将第2内存单元的数据加上cx的值,再放入cx,则cx=6622+2211=8833
其中内存中的情况为
需要注意的是内存单元是字节单元(8位),而在CPU中,是16位的寄存器,所以需要用两个内存单元。所以将[1]中的数据赋给一个16位的寄存器时,是将2211赋给寄存器。[1]
也是表示偏移地址。
指令
mov、add、sub三个常见的指令后面都有两个操作对象,两个对象可以是内存单元、段寄存器、寄存器的任意两个。当然也可以是立即数
CS和DS的区别
cs是值cpu执行的当前指令的段地址,ds是数据开始的段地址。
cs是告诉CPU,去哪个位置找内容当成指令去执行;
ds是告诉CPU,去哪个位置找内容当成数据被使用。
datastring =ds
codestring=cs
用到DS的例子:
mov ax, [100H]
这句指令的意思就是把地址[100H](属于数据)放入到寄存器ax里(直接寻址),
此时物理地址计算:ds*10H+100H
栈
栈是采用后进先出的原则(Last In First Out, LIFO),关于栈的寄存器有SS和SP,栈顶的段地址保存在SS,栈顶的偏移地址保存在SP里,任意时刻,SS:SP指向栈顶元素,pop和push执行时,CPU就能从SS和SP中得到栈顶的地址,压栈(push)和弹栈(pop)是以字位单位的,所以push每执行一次,SP都需要减2,pop每执行一次,需要加2。
push和popd的操作对象只有一个,可以是内存单元、段寄存器、寄存器的任意一个。
SP应该是这段地址空间的长度,比如将10000H-1000FH这段空间作为栈,则SS=1000H,SP=0010H。下面将ax,bx,cx中的数据压栈。
mov ax, 1000H
mov ss, ax
mov sp, 0010H
push ax
push bx
push cx
总结
段寄存器(CS,DS,SS)不能直接用立即数赋给它,需要用通用寄存器中转一下,而偏移寄存器却可以,比如IP和SP寄存器。栈指令(push和pop)也不能直接用立即数赋予,必须用寄存器。