免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3600 | 回复: 12
打印 上一主题 下一主题

CSAPP上的一道问题关于push pop操作 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-01-05 10:05 |只看该作者 |倒序浏览
这段时间在看CSAPP对练习题4.5不是很理解
       以下是他的测试代码,
       测试pop指令是先取数据再修改esp还是相反
      pushl tval
      movl  %esp,%edx
      popl  %esp
      movl  %esp,rval
      movl  %edx,%esp
这是生成的代码,其中tval,rval是局部变量
测试结果是rval=tval ,我觉得它说明的是pop指令先+4再取值
否则rval=tval+4了 但随后P244题4.11前他给出的结论恰恰相反
不知道大家怎么看
注 :我是在VC6.0环境下测试的由于对栈的操作不一样所以上面的代码要修改一下,且源与目标位置相反
# include <stdio.h>;
void main()
{
        unsigned int rval,tval = 1;
        {
                mov  edx,esp;  <---与push tval位置颠倒
                push tval;
                pop  esp;
                mov  rval,esp;
                mov  esp,edx;
        }
                printf("i %d\n", rval);
}

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
2 [报告]
发表于 2005-01-05 11:00 |只看该作者

CSAPP上的一道问题关于push pop操作

测试了一下,有和楼主同样的疑问。

  1. #include <stdio.h>;                                
  2.                                                   
  3. int     test1 = 5;                                    
  4. int     test2 = 6;                                    
  5.                                                   
  6. int main(void)                                    
  7. {                                                
  8.         __asm__ __volatile__ ("                  
  9.                         pushl   %0               
  10.                         movl    %%esp, %%edx      
  11.                         popl    %%esp            
  12.                         movl    %%esp, %1         
  13.                         movl    %%edx, %%esp"     
  14.                         :                        
  15.                         :"m"(test1), "m"(test2)   
  16.                         );                        
  17.         if (test1 == test2) printf("equal!\n");   
  18.         else printf("not equal!\n");              
  19.         return 0;                                 
  20. }
复制代码

这是用gcc编译的,结果是equal。

另外,VC下使用汇编是这样写吗?我没编译过去。

论坛徽章:
0
3 [报告]
发表于 2005-01-05 11:10 |只看该作者

CSAPP上的一道问题关于push pop操作

没看明白你的意思,我说说我的看法吧

popl %esp这个指令的处理我认为合其它的pop指令的处理有一些不一样,因为:

  1. popl val;
  2. 相当于:
  3. movl [%esp], val
  4. addl  4, %esp
复制代码

所以当这个val是esp的时候,我认为处理器读到这个指令会特殊处理,就像课后答案说的那样,这个指令相当于:mrmovl 0(%esp), %esp,就是说这个指令执行的时候是无法说清楚到底是先加4还是先取值,因为无论怎么解释似乎都说不过去,而是用这样的一条指令等效替代。

至于后面的对于pop指令的解释,我没有看出什么问题呀,它用了valA,valB存放esp的地址,而valA不变,用valA来读取原来栈中的值,然后valB +?4是上一个位置的值,用于更新esp的值,我不知道你说的“但随后P244题4.11前他给出的结论恰恰相反 ”指的是什么?

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
4 [报告]
发表于 2005-01-05 11:14 |只看该作者

CSAPP上的一道问题关于push pop操作

[quote]原帖由 "converse"]所以当这个val是esp的时候,我认为处理器读到这个指令会特殊处理,就像课后答案说的那样,这个指令相当于:mrmovl 0(%esp), %esp,就是说这个指令执行的时候是无法说清楚到底是先加4还是先取值,因为无论怎么解释似

论坛徽章:
0
5 [报告]
发表于 2005-01-05 11:15 |只看该作者

CSAPP上的一道问题关于push pop操作

嘿嘿 楼上的看一下题4.11和4.12的解答就明白了,我一开始的想法没有考虑的有类似中间变量的存储esp变化前的值
VC下面是这样加asm的,在VC下面主要注意的是源和目标的位置要颠倒,此外gcc和VC对栈的恢复不一样,所以有些代码位置要变
这个我在前面都有提及

论坛徽章:
0
6 [报告]
发表于 2005-01-05 11:16 |只看该作者

CSAPP上的一道问题关于push pop操作

我只是看了第一部分,我的c功力还勉强能应付,第二部分讲到操作系统就不知所云了,第三部分讲到网络更是一点都没有看,我决定了---用一年的时间(也许更多)来看这本书。

论坛徽章:
0
7 [报告]
发表于 2005-01-05 11:19 |只看该作者

CSAPP上的一道问题关于push pop操作

原帖由 "javacool" 发表:
嘿嘿 楼上的看一下题4.11和4.12的解答就明白了,我一开始的想法没有考虑的有类似中间变量的存储esp变化前的值
VC下面是这样加asm的,在VC下面主要注意的是源和目标的位置要颠倒,此外gcc和VC对栈的恢复不一样,所以..........


你的意思是不是既然后面4.11说了有中间变量来存放esp的值,为什么还要重新为pop esp来指定一条特殊的指令?还是别的什么意思,我还是不明白。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
8 [报告]
发表于 2005-01-05 11:22 |只看该作者

CSAPP上的一道问题关于push pop操作

原帖由 "javacool" 发表:
嘿嘿 楼上的看一下题4.11和4.12的解答就明白了,我一开始的想法没有考虑的有类似中间变量的存储esp变化前的值
VC下面是这样加asm的,在VC下面主要注意的是源和目标的位置要颠倒,此外gcc和VC对栈的恢复不一样,所以..........


可是如下的代码编译有错误啊:

  1. #include <stdio.h>;
  2. void main()
  3. {
  4. unsigned int rval = 5,tval = 6;
  5. {
  6. mov edx,esp;
  7. push tval;
  8. pop esp;
  9. mov rval,esp;
  10. mov esp,edx;
  11. }
  12. printf("i %d\n", rval);
  13. }
复制代码


错误是:

  1. --------------------Configuration: pop - Win32 Debug--------------------
  2. Compiling...
  3. pop.c
  4. D:\VC\pop\pop.c(6) : error C2065: 'mov' : undeclared identifier
  5. D:\VC\pop\pop.c(6) : error C2146: syntax error : missing ';' before identifier 'edx'
  6. D:\VC\pop\pop.c(6) : error C2065: 'edx' : undeclared identifier
  7. D:\VC\pop\pop.c(6) : error C2065: 'esp' : undeclared identifier
  8. D:\VC\pop\pop.c(7) : error C2065: 'push' : undeclared identifier
  9. D:\VC\pop\pop.c(7) : error C2146: syntax error : missing ';' before identifier 'tval'
  10. D:\VC\pop\pop.c(8) : error C2065: 'pop' : undeclared identifier
  11. D:\VC\pop\pop.c(8) : error C2146: syntax error : missing ';' before identifier 'esp'
  12. D:\VC\pop\pop.c(9) : error C2146: syntax error : missing ';' before identifier 'rval'
  13. D:\VC\pop\pop.c(10) : error C2146: syntax error : missing ';' before identifier 'esp'
  14. Error executing cl.exe.

  15. pop.obj - 10 error(s), 0 warning(s)
复制代码

论坛徽章:
0
9 [报告]
发表于 2005-01-05 11:26 |只看该作者

CSAPP上的一道问题关于push pop操作

converse的解释前面的我不太理解
我最后是看了他的Y86指令的6步分解,和题4.11 4.12的解释才明白的 push esp 和 pop esp应该有明确的执行结果把
converse的解释漏了一点就是只有最后写回寄存器的顺序按他那样写才能保证最后rval=tval 否则便是rval=tval+4了
aero看电子版 是E文的吗 还是手头紧没钱买:)

论坛徽章:
0
10 [报告]
发表于 2005-01-05 11:42 |只看该作者

CSAPP上的一道问题关于push pop操作

我又仔细地看了一下书,我原来的解释应该有误,先更正如下:
1)pop 指令并没有为pop esp这样的指令做特殊处理,上面的mrmovl 0(%esp), %esp只是作者为了让读者更好的理解这条指令的效果是esp中存放的是读取的值而不是esp + 4的值所写的,可以理解为等效的代码,但是处理器并不这样做。

2)那么,处理器处理到pop esp时应该怎样呢?就像中文版p243中的图4.18中写的那样,处理器用了两个暂存esp的值,一个是valA用于读取根据原来的esp的值读取栈中的值,一个valB用于更新esp,而在写回阶段首先更新esp为esp+4,然后把valA读取到的栈中的值来更新esp,就是说esp+4在前,而把栈中的值写如esp在后,这样这条指令执行起来的最后(注意是最后的)效果就是esp的值是栈中的值,而不是esp+4

附,图4.18中对pop指令的解释:

  1. 阶段                         popl rA
  2. 取值                     icode:fun <-  M1[PC]
  3.                                       rA:rB <- M1[PC+1]
  4.                                       valP <- PC+2
  5. 解码                     valA <- R[%esp]
  6.                                       valB <- R[%esp];这样vala和valb都是esp
  7.                                                                 ;的值
  8. 执行                     valE <- valB +?4;此时valE为esp + 4
  9. 访存                     valM <- M4[valA];此时valM是栈中的值
  10. 写回                     R[%esp] <- valE ;更新esp + 4
  11.                                      R[rA] <- valM;当ra是esp的时候此时esp就是
  12.                                       ;栈中的值
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP