脑袋笨,看了很久才明白
书中有这样一道练习题,下面程序中,ret指令执行后,(ip)=0,cs:ip指向代码的第一条指令
assume cs:code
stack segment
db 16 dup(0)
stack ends
code segment
mov ax,4c00h
int 21H
start:mov ax,stack
mov ss,ax
mov sp,16
mov ax,0
push ax
mov bx,0
ret
code ends
end start 书中说,cpu执行完ret指令时,进行下面2步操作
(1)(ip)=((ss)*16+sp)
(2)(sp)=(sp)+2
因为看不懂,所以运行debug了下

然后照搬公式(1)(ip)=((ss)*16+sp),发现(ss)*16+sp=0bdf0+000e=0bdfe,怎么就得到0bdfe不等于0啊,怎么回事?原来0bdfe就是物理地址啊,(0bdfe)就是物理地址0bdfe指向的内容,我们用-d指令可以这样查看0bdf:e
可以看到该地址内容如图

0bdf:0000段中 0bdf:e对应00,然后0bdf:f对应剩下的00
所以这个时候ip指向的内容就是00
后来才明白,cpu执行ret其实不就是pop ip么?将此时sp指向的东东放到ip中,sp指向的东东也就是(ss)*16+sp这个地址中的数值啊!mov ax,0 push ax的作用就是将此时栈顶元素设置为0,然后执行push ip就是将ax抛出给ip了。
备注:
db 16 dup(1) 看下这个时候内存中是如何放置信息的

看到的都是16进制,所以01 中0占了4位,1也占了4位,恰好是8位,也就是一个字节
所以每2个紧挨一起的数字就占用了一个内存单元。
所以0bdf:0000指向的就是最开始的01
备注:关于mov sp,16,用图来理解

一开始的时候sp为0000,执行网mov ss,ax mov sp,16后,sp变为0010 *16也就相当于16进制1*16,所以变为0010,注意看,可以看到0bdf指向了另起一行的首地址,因为stack 在一开始的时候默认为16个字节,也就是0bdf:0-0bdf:f 所以sp变为0010也就是指向栈底了。

234

被折叠的 条评论
为什么被折叠?



