学习《汇编语言》第二章第三章后个人的一点理解。
CS、IP
cs、ip是代码段寄存器和指令指针寄存器,执行指令时需要获取代码所在的地址。
r
r cs
1000
r ip
0
r
以上代码为设置cs、ip的地址。cs为段地址,ip为偏移地址。cs+ip即为代码所在地址。此时代码所在地址为1000:0
此时往1000:0添加指令:
a 1000:0
mov ax,1000
mov bx,2000
add ad,bx
依次添加指令,设置ax=1000,bx=2000,ax=ax+bx。不再输入时直接回车。
再次通过"r"确认当前地址,“u 1000:0"查看指令及所在地址、机器码长度。
输入t,此时CPU执行cs:ip所在地址包含的指令,即"mov ax,1000”,如图所示:
注意到,指令指针增加了3,这是因为8086CPU中,一个内存单元为8bit,也就是1字节;而在16进制下的1位便等同于二进制的4位,16进制下的2位等同于二进制下的1个字节。这里的机器码占3个字节,故而执行第一条指令结束后,内存单元+3,ip+3。
继续输入t,在执行完所有指令后,ip应为8,ax=3000.
DS
ds为段地址寄存器,存放将要访问数据的段地址。
查看此时ds的值,为0AF5。输入"d 0AF5"查看地址所存放的数据。
输入r查看寄存器信息
尝试将ds段寄存器中的0地址字单元数据送入cx寄存器。由于指令指针所指的地址是1000:8,故输入指令为
a 1000:8
mov cx,[0]
查看0地址字单元数据
在执行指令后,应cx=20CD
这是因为8086CPU中,寄存器按字存储,1个字等于2个字节,0地址字单元由内存单元0(低位)和内存单元1(高位)组成。高地址内存单元存放字型数据的高位字节,低地址内存单元存放字型数据的低位字节。
同理,可将ax寄存器的值写入0单元和1单元中。
SS、SP
任意时刻,SS:SP指向栈顶元素,push和pop指令执行时,CPU从SS和SP获取栈顶的地址。类似cs、ip,ss存放栈顶的段地址,sp存放栈顶的偏移地址,同时,sp也决定着栈是否溢出。
输入r查看当前ss、sp的值
我们可以自己设定栈顶地址。
r ss
2000
r sp
80
栈中没有元素时,sp指向栈的最底层,假设2000:0080处存放其他程序的代码段,栈为空时,ss:sp-2即为第一次push时,实际的栈顶地址。
修改ax的值为1234,并push入栈。查看栈顶的值。
r ax
1234
u 1000:F
push ax
输入t。可以看到,执行指令后,sp先-2,80-2=7E,此时栈顶存放的数据为3412
将ds[0]地址字单元的数据压入栈中。
a 1000:10
push [0]
如上图所示,0地址单元的数据为0030。压入栈中后,栈顶低位存放00,高位存放30,sp=007C。如下图所示。
取出栈顶的值,送入bx
a 1000:14
pop bx
高位存放高地址,低位存放地址,故bx最终为0559,SP+2