新知识:
DS确定要访问的内存的段地址。
配合命令中的偏移地址 [0],可以确定要访问的字节。
SS:SP 确定栈顶位置。
第二节代码
mov bx,1000H
mov ds,bx
mov al,[0]
提问:为什么不能直接mov ds,1000H ?
答:就是不行。
提问:若令ax=6030,再mov [0],ax,会得到什么结果?
答:对应地址0000:0处会依次写入低地址30,高地址60。
相应的,把 2000:0~3依次设为23,11,22,66。
再设置ds=2000H,执行mov ax,[0]。
得到ax=1123,即2000:0开始的前两个字节依次送入al,ah。
还能看到右下角DS:0002 = 6622,是说下一个16bit的“字”为6622。
第4节代码
mov ax,1000H
mov ds,ax
mov ax,11316
mov [0],ax
mov bx,[0]
mov bx,[2]
mov [2],bx
其中mov ax,11316这句,书上有点问题。
说是10进制11316会转成16进制2C34。
但是debug里,只允许输入16进制的2C34,不能输入10进制数。
提问:add与sub可以对段寄存器ds操作吗?
答:不可以。试图写入命令时报错。
#8086CPU不保证我们对栈的操作不会越界。
甚至不保证栈连续。
例如对SS:SP=1000:0
执行push ax后 (ax=2C24H)
SP=FFFE
可以看到1000:FFF0的末端为AX的值,即24 2C
我们知道,push操作的时候,SP=SP-2,按理说1000:0退2格,应该要去0FFF:FFFE。
但由于初始SP=0,SP是个无符号数,减2之后就变成了FFFE。
于是最终SS:SP=1000:FFFE,反而跑到后面去了。
但是!我们可以利用这种“头尾相接”的性质,将SS=1000H定位栈段,将SP=0约定为栈空状态。
可见一个栈段最大为0~FFFFH,变化范围是4个16进制,每个数字表示一字节的地址。
一个栈段最大长度,即2^16B=64KB。
实验2
在EAU中使用段寄存器ds
例: e ds:0 11 22 33 44 55 66 (在1000:0里依次写入数据)
例:a ds:0 (从1000:0开始写入汇编命令)
例:U ds:0(从1000:0开始解读指令)
(1)
mov ax,ffff
mov ds,ax
mov ax,2200
mov ss,ax
mov ax,[0]
add ax,[2]
mov bx,[4]
add bx,[6]
push ax
push bx
pop ax
pop bx
push [4]
push [6]
(2)debug实验
提问:为什么push过程中会改变2000:0~f的值。
答:
因为你把ss=2000,sp=0010
第一次mov ax,3132之后,ax=3123
再push ax,相当于在2000:000e~000f写入了23,31。
第二次mov ax,3366之后,ax=3366
再push ax,相当于在2000:000c~000d写入了66,33。
所以2000:0~f会改变。