| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3023 人关注过本帖
标题:一道面试题
只看楼主 加入收藏
yuki
Rank: 2
等 级:新手上路
威 望:5
帖 子:508
专家分:0
注 册:2005-2-4
收藏
得分:0 

出现随机的数字,我猜想可能是编译器编译以后进行代码优化时所造成的,我上面展开的汇编语句,并不是所有编译器都这么做的,我想如果这么看似简单的一个函数作为面试题,不会让你得出是一个随机值这么简单,这样的结果学了程序的人应该一眼都能看出来。


我想这个并不是一个很好的解释,希望有其他高手给点意见。

[此贴子已经被作者于2007-9-3 16:57:46编辑过]


我们都在命运湖上荡舟划桨,波浪起伏使我们无法逃离孤行;如果我们迷失方向,波浪将指引我们穿过另一天曙光
2007-09-03 16:56
酒肉弥勒佛
Rank: 3Rank: 3
等 级:新手上路
威 望:8
帖 子:399
专家分:0
注 册:2006-6-6
收藏
得分:0 
面试题出的这么含糊不清,比问你int占多少空间一样还离谱,估计要考的是break没有,该怎么执行

编程是为了提高效率,好的程序是因为他的高效;在编程的道路上,永远追逐高效的算法
2007-09-03 17:01
爱以走远
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:52
帖 子:7542
专家分:21
注 册:2007-3-16
收藏
得分:0 
以下是引用yuki在2007-9-3 16:49:57的发言:

收回上面的话,这题目的确有意思,仔细想了想运行结果为0

由于switch()没有break语句一路运行到底。

比如func(1)时
运行30; 20; 16; 0;
仔细看看,这些语句并非无意义。

化成汇编语言来看。
30; => mov ax, 30d
20; => mov ax, 20d
16; => mov ax, 16d
0; => mov ax, 0d
最后ax中的结果是0
执行return b其实就是对应汇编语句如下:
mov (WORD PTR)b, ax
ret

注:BC3.1运行结果为0,并非不可预料的值。


mov (WORD PTR)b, ax
这句你是重c语言里那一句翻译过来的


   好好活着,因为我们会死很久!!!
2007-09-03 17:02
yuki
Rank: 2
等 级:新手上路
威 望:5
帖 子:508
专家分:0
注 册:2005-2-4
收藏
得分:0 

我似乎想到一点,有些编译器可能在调用函数前先保护寄存器ax
push ax
.
.
.
.
pop ax
mov WORD BYTE b, ax
ret
在ax没有初始化时,就是一个不可预料的值,这样返回的就是一个不可预料的值。

希望有更恰当的回答。


我们都在命运湖上荡舟划桨,波浪起伏使我们无法逃离孤行;如果我们迷失方向,波浪将指引我们穿过另一天曙光
2007-09-03 17:02
yuki
Rank: 2
等 级:新手上路
威 望:5
帖 子:508
专家分:0
注 册:2005-2-4
收藏
得分:0 
以下是引用爱以走远在2007-9-3 17:02:39的发言:

mov (WORD PTR)b, ax
这句你是重c语言里那一句翻译过来的

return b;
这一句语句可以对应两句汇编,即
mov WORD PTR b, ax
ret ;这一句是返回函数调用点之后的那个语句


int main()
{
func(1); <- 函数调用点
return 0; <- 返回点
}


我们都在命运湖上荡舟划桨,波浪起伏使我们无法逃离孤行;如果我们迷失方向,波浪将指引我们穿过另一天曙光
2007-09-03 17:04
爱以走远
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:52
帖 子:7542
专家分:21
注 册:2007-3-16
收藏
得分:0 
return b;
这一句语句可以对应两句汇编,即
mov WORD PTR b, ax
ret ;这一句是返回函数调用点之后的那个语句
没听说过

   好好活着,因为我们会死很久!!!
2007-09-03 17:13
yuki
Rank: 2
等 级:新手上路
威 望:5
帖 子:508
专家分:0
注 册:2005-2-4
收藏
得分:0 
以下是引用爱以走远在2007-9-3 17:13:45的发言:
return b;
这一句语句可以对应两句汇编,即
mov WORD PTR b, ax
ret ;这一句是返回函数调用点之后的那个语句
没听说过

汇编语言过程调用是怎样一个情况呢?
对于func有一个参数, 并且参数的类型为int,也就是2个字节(16位编译器中)
C语言中调用func,如下形式
func(1); // 值1传入参数
同样汇编语言中调用过程func,如下
mov ax, 1d
push ax
CALL func
在执行过程前,需要将参数压栈,执行了CALL func以后也就是间接执行了如下语句
push cs
pop ip
mov ax, SEG func
push ax
首先将当前代码段保存和指令寄存器,然后func所在的代码段压栈了,执行了CALL以后系统从堆栈中取出func所在的代码段,并充定向当前代码段:
pop cs
这样一来,开始的下一条指令cs:ip就从func内的第一条语句开始执行。
运行到这里堆栈内的情况是
[?][?][?][0x0001][ip][cs][?][?]...[?] (x86体系堆栈是从左往右增长的)
sp ss
当前栈顶指正指向cs那一块,也就是保存的原来调用点代码段的段地址,我们如何获得压栈以后的参数0x0001呢,很容易,如下语句可完成
push bp; 保存一下bp
mov bp, sp-4; x86的堆栈单元是2个字节为单位的
mov ax, WORD PTR [bp] ;取参数0x0001
pop bp
好了,参数有了,这样就可以运行程序了,当这个过程结束后必须返回到调用点,即ret语句,没有这个语句程序将顺序执行到一个不可预料的地步。(上述代码构建一个框架指针)
ret语句作的工作是
pop ip
pop cs
然后令ip = ip + 1 -> 这个应该是cpu做的工作,继续执行cs:ip的代码,也就是调用点之后的代码。

[此贴子已经被作者于2007-9-3 18:27:10编辑过]


我们都在命运湖上荡舟划桨,波浪起伏使我们无法逃离孤行;如果我们迷失方向,波浪将指引我们穿过另一天曙光
2007-09-03 18:11
conanwangcsu
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2007-9-3
收藏
得分:0 
回复:(taojingwen)一道面试题

高手高手!
似懂非懂,学习中。。。

2007-09-03 18:25
爱以走远
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:52
帖 子:7542
专家分:21
注 册:2007-3-16
收藏
得分:0 

呵呵
yuki兄很认真 写拉这么多
执行程序的下一条指令的确是cs:ip
但是我感觉这个和我问的没什么联系吧 。
我只是问return b;
这一句语句可以对应两句汇编,即
mov WORD PTR b, ax
ret ;
在汇编里 ax是一个寄存器, 他怎么会在最后把这个寄存器的值给b呢?
要给b那么在c里也该有b=?;
它既然没有这一句 , 那你又为什么在汇编里加一句mov WORD PTR b, ax呢


   好好活着,因为我们会死很久!!!
2007-09-03 18:42
yuki
Rank: 2
等 级:新手上路
威 望:5
帖 子:508
专家分:0
注 册:2005-2-4
收藏
得分:0 
以下是引用爱以走远在2007-9-3 18:42:13的发言:

呵呵
yuki兄很认真 写拉这么多
执行程序的下一条指令的确是cs:ip
但是我感觉这个和我问的没什么联系吧 。
我只是问return b;
这一句语句可以对应两句汇编,即
mov WORD PTR b, ax
ret ;
在汇编里 ax是一个寄存器, 他怎么会在最后把这个寄存器的值给b呢?
要给b那么在c里也该有b=?;
它既然没有这一句 , 那你又为什么在汇编里加一句mov WORD PTR b, ax呢

对,这个问题提得好,我刚想到。
这里是将b的执返回上去,也就是得把b的值传递给AX

mov ax, WORD PTR b ;由于b没有初始化也没有赋值,则返回的是一个不可预料的值。

但是,有些编译器结果为何是0。
有些编译器在生成目标代码的时候,发现b变量没有被引用,则返回b的值也就是相当于将经过最后一步操作的AX的值返回了(因为编译器认为b在这里并没有意义,也就是为什么许多编译器会警告b没有被引用)

感谢这位兄弟的问题启发了我。


我们都在命运湖上荡舟划桨,波浪起伏使我们无法逃离孤行;如果我们迷失方向,波浪将指引我们穿过另一天曙光
2007-09-03 18:48
快速回复:一道面试题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.019025 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved