您的位置:首页 > 其它

在牛客网看到这样的一个选择题,给出自己的见解

2015-04-14 08:56 232 查看
题目是:

以下程序输出是____。

A 编译阶段报错运行阶段报错

B a = 10, *p = 10

C a = 20, *p = 20

D a = 10, *p = 20

E a = 20, *p = 10

运行时,得到的是答案是D,通过命令objdump -S a.o反汇编:
0000000000400916 <main>:

#include <iostream>

using namespace std;

int main(void)

{

400916: 55 push %rbp

400917: 48 89 e5 mov %rsp,%rbp

40091a: 53 push %rbx

40091b: 48 83 ec 28 sub $0x28,%rsp

40091f: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax

400926: 00 00

400928: 48 89 45 e8 mov %rax,-0x18(%rbp)

40092c: 31 c0 xor %eax,%eax

const int a = 10;

40092e: c7 45 dc 0a 00 00 00 movl $0xa,-0x24(%rbp) //把10放入%rbp - 0x24地中存起来

int * p = (int *)(&a);

400935: 48 8d 45 dc lea -0x24(%rbp),%rax //把%rbp - 0x24放入寄存器rax中,注意,此处不是值,而是把地址放入这个寄存器中,rax寄存器保存的是地址。

400939: 48 89 45 e0 mov %rax,-0x20(%rbp) //把寄存器rax的值(也就是上一步//得到的地址)放入地址%rbp
- 0x20中存起来。

*p = 20;

40093d: 48 8b 45 e0 mov -0x20(%rbp),%rax //同上一步,只是反过来赋值无变化

400941: c7 00 14 00 00 00 movl $0x14,(%rax) //把20放入%rbp-0x24地址中存起来,//也就是把存放a的地址中,保存了20.此处应该是a
= 20了,*p = 20。

cout<<"a = "<<a<<", *p = "<<*p<<endl;

400947: 48 8b 45 e0 mov -0x20(%rbp),%rax

40094b: 8b 18 mov (%rax),%ebx

40094d: be 84 0a 40 00 mov $0x400a84,%esi

400952: bf 80 10 60 00 mov $0x601080,%edi

400957: e8 84 fe ff ff callq 4007e0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>

40095c: be 0a 00 00 00 mov $0xa,%esi

400961: 48 89 c7 mov %rax,%rdi

400964: e8 17 fe ff ff callq 400780 <_ZNSolsEi@plt>

400969: be 89 0a 40 00 mov $0x400a89,%esi

40096e: 48 89 c7 mov %rax,%rdi

400971: e8 6a fe ff ff callq 4007e0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>

400976: 89 de mov %ebx,%esi

400978: 48 89 c7 mov %rax,%rdi

40097b: e8 00 fe ff ff callq 400780 <_ZNSolsEi@plt>

400980: be 10 08 40 00 mov $0x400810,%esi

400985: 48 89 c7 mov %rax,%rdi

400988: e8 73 fe ff ff callq 400800 <_ZNSolsEPFRSoS_E@plt>

return 0;

40098d: b8 00 00 00 00 mov $0x0,%eax

}



从上面的加粗部分汇编以及我的注释中可以看出,在汇编当中还没有进入打印时,在相应的内存中已经对a修改为20了,而且这个值也没有保存在寄存器中,说明后面的打印是需要访问这个地址的。答案是会得到a = 10, *p = 20,也就是说a没有得到更新,我把代码改一下,使得对a的定义改为:

const volatile a = 10.这样,对a的访问强制访问内存,编译执行后得到了a = 20, *p = 20的答案。由此可以看出估计是取a值的时候直接从寄存器里面取值了,但是汇编代码中a的值没有存在寄存器里面,哪里错了?我考虑对修改后的代码进行反汇编,得到:

0000000000400916 <main>:

#include <iostream>

using namespace std;

int main(void)

{

400916: 55 push %rbp

400917: 48 89 e5 mov %rsp,%rbp

40091a: 41 54 push %r12

40091c: 53 push %rbx

40091d: 48 83 ec 20 sub $0x20,%rsp

400921: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax

400928: 00 00

40092a: 48 89 45 e8 mov %rax,-0x18(%rbp)

40092e: 31 c0 xor %eax,%eax

const volatile int a = 10;

400930: c7 45 dc 0a 00 00 00 movl $0xa,-0x24(%rbp)

int * p = (int *)(&a);

400937: 48 8d 45 dc lea -0x24(%rbp),%rax

40093b: 48 89 45 e0 mov %rax,-0x20(%rbp)

*p = 20;

40093f: 48 8b 45 e0 mov -0x20(%rbp),%rax

400943: c7 00 14 00 00 00 movl $0x14,(%rax)

cout<<"a = "<<a<<", *p = "<<*p<<endl;

400949: 48 8b 45 e0 mov -0x20(%rbp),%rax

40094d: 8b 18 mov (%rax),%ebx

40094f: 44 8b 65 dc mov -0x24(%rbp),%r12d

400953: be 94 0a 40 00 mov $0x400a94,%esi

400958: bf 80 10 60 00 mov $0x601080,%edi

40095d: e8 7e fe ff ff callq 4007e0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>

400962: 44 89 e6 mov %r12d,%esi

400965: 48 89 c7 mov %rax,%rdi

400968: e8 13 fe ff ff callq 400780 <_ZNSolsEi@plt>

40096d: be 99 0a 40 00 mov $0x400a99,%esi

400972: 48 89 c7 mov %rax,%rdi

400975: e8 66 fe ff ff callq 4007e0 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>

40097a: 89 de mov %ebx,%esi

40097c: 48 89 c7 mov %rax,%rdi

40097f: e8 fc fd ff ff callq 400780 <_ZNSolsEi@plt>

400984: be 10 08 40 00 mov $0x400810,%esi

400989: 48 89 c7 mov %rax,%rdi

40098c: e8 6f fe ff ff callq 400800 <_ZNSolsEPFRSoS_E@plt>

return 0;

400991: b8 00 00 00 00 mov $0x0,%eax

}

对比一下这两个汇编,发现一模一样,看来是我们的objdump命令的问题了,我估计objdump -S命令应该得到的是非常标准没有经过优化的汇编代码(有大神可以可以确定的话,请告诉我,给出你从哪里看到的,比如书本名Pxxx页)。

到这里,结束了,你应该早就明白了,我扯远了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐