在我的印象中,加减剩除运算都是先将内存数据拷贝到寄存器中,然后通过运算指令完成运算后再将结果写回内存,为什么我反汇编了一个段程序后发现可以直接操作内存数据呢?求解惑!
int var = 3;
void *pThreadFunc(void *args)
{
++var;
printf("thread:%d\n", var);
return NULL;
}
int main()
{
++var;
pthread_t id;
pthread_create(&id, NULL, pThreadFunc, NULL);
sleep(10);
return 0;
}
反汇编出来后是:
00000000004006d0 <main>:
4006d0: 48 83 ec 18 sub $0x18,%rsp
4006d4: 31 c9 xor %ecx,%ecx
4006d6: ba 00 07 40 00 mov $0x400700,%edx
4006db: 48 8d 7c 24 08 lea 0x8(%rsp),%rdi
4006e0: 31 f6 xor %esi,%esi
4006e2: 83 05 c3 04 20 00 01 addl $0x1,0x2004c3(%rip) # 600bac <var>
4006e9: e8 ba fe ff ff callq 4005a8 <[email protected]>
4006ee: bf 0a 00 00 00 mov $0xa,%edi
4006f3: e8 c0 fe ff ff callq 4005b8 <[email protected]>
4006f8: 31 c0 xor %eax,%eax
4006fa: 48 83 c4 18 add $0x18,%rsp
4006fe: c3 retq
4006ff: 90 nop
0000000000400700 <_Z11pThreadFuncPv>:
400700: 48 83 ec 08 sub $0x8,%rsp
400704: 8b 35 a2 04 20 00 mov 0x2004a2(%rip),%esi # 600bac <var>
40070a: bf 38 08 40 00 mov $0x400838,%edi
40070f: 31 c0 xor %eax,%eax
400711: 83 c6 01 add $0x1,%esi
400714: 89 35 92 04 20 00 mov %esi,0x200492(%rip) # 600bac <var>
40071a: e8 59 fe ff ff callq 400578 <[email protected]>
40071f: 31 c0 xor %eax,%eax
400721: 48 83 c4 08 add $0x8,%rsp
400725: c3 retq
400726: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40072d: 00 00 00
第一处标红处:addl $0x1,0x2004c3(%rip)
第二处标红处:add $0x1,%esi
第一处标红处就是我的困惑处?这是为什么呢?
------解决思路----------------------
当然是可以的,你原来的印象错误了;还是看下指令集吧,各个指令支持什么样类型的操作数据模式,都有的。
------解决思路----------------------
《The Intel 64 and IA-32 Architectures Software Developer's Manual》
------解决思路----------------------
你这个好像是 linux 类环境下的吧,我对这个没怎么接触过;从代码上来看,调用函数是以 edi/esi... 作为第一二...个参数的吧,下面部分有将 var 作为第二个参数,就是要在 esi 里了,所以它采用了给 esi 增 1 然后存回到内存里,当然了它也可以采用先给内存增 1 然后再取到 esi 里,这也只是不同方式的选择,就如增 1 为什么不采用 inc 而是 add 1,... 指令;而上面部分即 main() 里,除了给 var 增 1 外没有再使用到它,所以就简单直接地给其增 1 了。
同样功能的实现,可能会有多种方法,究竟采用哪个,和代码优化以及编译功能通用性都有关吧。
------解决思路----------------------
我的建议一般都比较高大上,照做的话,肯定最费时费力。
但为什么还有那么多登山者登山时,非得用最费时费力的方法,找最费时费力的路线呢?
------解决思路----------------------
当然可以直接操作内存的 汇编已经不是中间语言了