当前位置: 代码迷 >> 汇编语言 >> 汇编指令的算术运算能否直接操作内存,addl
  详细解决方案

汇编指令的算术运算能否直接操作内存,addl

热度:260   发布时间:2016-05-02 04:27:49.0
汇编指令的算术运算可否直接操作内存,addl
在我的印象中,加减剩除运算都是先将内存数据拷贝到寄存器中,然后通过运算指令完成运算后再将结果写回内存,为什么我反汇编了一个段程序后发现可以直接操作内存数据呢?求解惑!
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 了。
同样功能的实现,可能会有多种方法,究竟采用哪个,和代码优化以及编译功能通用性都有关吧。
------解决思路----------------------
我的建议一般都比较高大上,照做的话,肯定最费时费力。
但为什么还有那么多登山者登山时,非得用最费时费力的方法,找最费时费力的路线呢?
------解决思路----------------------
当然可以直接操作内存的  汇编已经不是中间语言了