关于甲鱼老师讲的第十章call指令和检测点10.2的问题
刚在学习小甲鱼老师的汇编视频,看到第十章call指令,讲的是cpu执行call指令时,进行两步操作:1、将当前的ip或cs和ip压入栈中;2、转移(jmp)。本人认为老师讲的将当前的ip压入栈中这样说不恰当,应该是IP的值先变成call指令后的第一个字节的地址,然后才被压入栈中。然而老师在讲后边call和ret指令时,又强调了ip指向了call下一条指令,再将ip入栈。
这样就给很多初学汇编的同学造成了误解(包括我本人),以为两种指令的ip入栈不同,导致很多同学发帖问检测点10.2的答案ax的值为什么是6,表示不懂。以下为检测点10.2
下面的程序执行后,ax中的数值为多少?
内存地址 机器码 汇编指令 执行后情况
1000:0 b8 00 00 mov ax,0 ax=0 ip指向1000:3
1000:3 e8 01 00 call s pop ip ip指向1000:7
1000:6 40 inc ax
1000:7 58 s:pop ax ax=6
现在没搞懂的同学应该知道为什么是6了吧。
这只是我本人的理解,不知道是否正确,说错的地方望大家给我指正。如果正确也希望能帮助大家走出误区,解决检测点10.2这道题目,谢谢! 本帖最后由 兰陵月 于 2016-12-15 13:04 编辑
"本人认为老师讲的将当前的ip压入栈中这样说不恰当,应该是IP的值先变成call指令后的第一个字节的地址,然后才被压入栈中。然而老师在讲后边call和ret指令时,又强调了ip指向了call下一条指令,再将ip入栈。"
你上述的理解是错误~CPU运行指令的步骤不知道你是否还记得,
CPU执行指令的步骤:
1、读入当前指令;
2、IP=IP+1
3、执行第1步已经读入的指令。
所以说当读入CALL指令那一行时,IP指针就已经自动指向了CALL的下面一条指令,因此执行CALL指令的时候,直接压入IP就是了,因为此时的IP就已经指向了下一条指令。
不知道解释得是否正确,请批评指正~~{:10_256:} 下面的程序执行后,ax中的数值为多少?
内存地址 机器码 汇编指令 执行后情况
1000:0 b8 00 00 mov ax,0 ax=0 ip指向1000:3
1000:3 e8 01 00 call s 读入此指令时,IP偏移为6,将偏移6压入栈,转到标号s执行。
1000:6 40 inc ax
1000:7 58 s:pop ax 弹出栈,因为压入的是6,所以AX结果为6,因为没有RET指令,因此IP不会跳转到1000:6处执行,将会直接执行s:pop ax后面的语句,1000:6将被直接跳过。
兰陵月 发表于 2016-12-15 12:52
下面的程序执行后,ax中的数值为多少?
内存地址 机器码 汇编指令 执行后情况
你2楼说的是正确的,但是3楼说的ip偏移地址为6,这里是错误的,老师讲过 e8 01 00 此处机器码的0001就是偏移地址,此偏移地址是由标号s处的地址(7)-call指令后的第一个字节地址(6)而得来的。 通过学习我是这样理解的 兰陵月 发表于 2016-12-15 12:46
"本人认为老师讲的将当前的ip压入栈中这样说不恰当,应该是IP的值先变成call指令后的第一个字节的地址,然 ...
你说的这里我不太记得了,但是你说ip=ip+1,我觉得不应该加1,加的应该是这条指令的所占字节数,得出来的就是下条指令的地址,这样就和我说的是一样的了。按你说的ip+1,如果这条指令占3个字节,即使ip+1,得出来的还是在这条指令中的位置,这样cpu执行下条指令时就会出错 王小2 发表于 2016-12-15 15:48
你说的这里我不太记得了,但是你说ip=ip+1,我觉得不应该加1,加的应该是这条指令的所占字节数,得出来的 ...
IP=IP+1的意思就是指向下一条指令的地址,不是纯粹的数字上+1,我是照书上解释的,请不要理解为IP+1就是IP+数字1~~{:10_262:} 王小2 发表于 2016-12-15 15:40
你2楼说的是正确的,但是3楼说的ip偏移地址为6,这里是错误的,老师讲过 e8 01 00 此处机器码的0001就是 ...
e8 01 00,这个机器码的意思,你要反过来理解~
IP不是按照你这么推断的,你这是反推断IP结果值,你只要理解CPU的工作原理,就不难明白IP是怎么变化的了。
视频中小甲鱼的解释并没有错,但请仔细多听几次,他视频说到的那种推断是从另外一个角度来解释IP的变化的。
CPU加电启动后,就会永远按照CS:IP指向的地址一直不停执行下去,直到来到你编写的程序,然后就是下面顺序。
【这些图片来自王爽《汇编语言》(第2版)电子书第25页到第29页】
本帖最后由 兰陵月 于 2016-12-16 13:04 编辑
所以按照上面图片中的解释:
内存地址 机器码 汇编指令
................ ..................... ..............
本处指令读取后执行前,CS:IP=1000:0000,本条执行执行完后,CPU执行CS:IP指向的指令
1000:0 b8 00 00 mov ax,0
1、读取b8 00 00,2、CS:IP=1000:0003,3、执行指令 mov ax,0
1000:3 e8 01 00 call s
1、读取e8 01 00,2、CS:IP=1000:0006(IP=IP+本条指令长度即3,所以IP=3+3),3、执行call s
CALL S执行过程:①将当前的IP或CS和IP压入栈:当前IP=6,所以将6压入栈;②转移到S处执行。
1000:6 40 inc ax
1000:7 58 s:pop ax
1、读取pop ax,2、CS:IP=1000:0008(此前经过CALL指令,IP的值已经变成了7);3、执行pop ax。
最后一条第2部为什么IP变成8,请详细阅读CALL指令的执行,里面解释了如何跳转,跳转的长度是多少,例如本例题中的短转移,标号S的值怎么来的,S实际上就是IP+0001,即6+1(这个6就是读取第2部指令完后IP的值,这个0001也就是e8 01 00的后两个字节),S在题目中代表跳转的偏移值,如果跳的更远,比如说跳到1000:8,则e8后面就应该是0200,即e8 02 00。
不知道这样解释,楼主是否清楚~~~
诶~这个蛋疼的排版,你将就着看吧~~ 本帖最后由 兰陵月 于 2016-12-16 12:58 编辑
关于JMP 后面相关标号的处理,CALL S后面跳转到S那一部分与JMP功能一样~~~请看下图~
小甲鱼同志的讲解应该是附录3里面的意思~
图片来自王爽《汇编语言》第2版电子书,附录3
兰陵月 发表于 2016-12-16 12:52
关于JMP 后面相关标号的处理,CALL S后面跳转到S那一部分与JMP功能一样~~~请看下图~
小甲鱼同志的讲解应 ...
谢谢你啦,真是用心良苦啊{:5_100:} 王小2 发表于 2016-12-16 14:23
谢谢你啦,真是用心良苦啊
这玩意必须得真懂,真明白,否则到后面越学越纠结,越来越看不懂~你懂了就好~,呵呵!
其实我回答你的问题,我也是一个复习的过程,我也得到了进步~~
一起进步~~{:10_332:}{:10_332:} 兰陵月 发表于 2016-12-16 10:33
所以按照上面图片中的解释:
内存地址 机器码 汇编指令
楼主这个很棒。
页:
[1]