汇编学习笔记——001

在学习过程中,发现一道用汇编解决的C语言问题

#include <stdio.h>

int main() {
	int j = 5,num;
	num = (++j) + (++j) + (++j);
	printf("num = %d\n", num);
	return 0;
}

这道题在计算中,我们会认为结果为num = 6+7+8 = 21

在编译完成后发现结果为22

使用反编译工具将a.out反编译为汇编语言后,发现了其中的奥秘

   0x400526 <main>       push   rbp
   0x400527 <main+1>     mov    rbp, rsp
   0x40052a <main+4>     sub    rsp, 0x10
   0x40052e <main+8>     mov    dword ptr [rbp - 8], 5
   0x400535 <main+15>    add    dword ptr [rbp - 8], 1
   0x400539 <main+19>    add    dword ptr [rbp - 8], 1
   0x40053d <main+23>    mov    eax, dword ptr [rbp - 8]
   0x400540 <main+26>    lea    edx, [rax + rax]
   0x400543 <main+29>    add    dword ptr [rbp - 8], 1
   0x400547 <main+33>    mov    eax, dword ptr [rbp - 8]
   0x40054a <main+36>    add    eax, edx
   0x40054f <main+41>:  mov    eax,DWORD PTR [rbp-0x4]
   0x400552 <main+44>:  mov    esi,eax
   0x400554 <main+46>:  mov    edi,0x4005f4
   0x400559 <main+51>:  mov    eax,0x0
   0x40055e <main+56>:  call   0x400400 <printf@plt>
   0x40054f <main+41>              mov    eax, dword ptr [rbp - 4]
   0x400552 <main+44>              mov    esi, eax
   0x400554 <main+46>              mov    edi, 0x4005f4
   0x400559 <main+51>              mov    eax, 0
   0x40055e <main+56>              call   printf@plt <0x400400>

   0x400563 <main+61>              mov    eax, 0
   0x400568 <main+66>              leave
   0x400569 <main+67>              ret

可以看出这里的操作相当于num = 7+7+8 = 22

这个结果是VC6编译器的“习惯”导致的
他编译器背后是怎么运作的呢?通过反编译我们可以看出
j的结果是有三个自增相加,他会优先将前两个自增之后再将他们相加。
然后在把这个结果与最后一个自增结果相加
所以得到的num = 7+7+8 =22
而不是21

相关内容记录

lea对变量没有影响是取地址,对寄存器来说加[]时取值,第二操作数不加[]非法
mov对变量来说没有影响是取值,对寄存器来说是加[]时取地址,第二操作数不加[]是取值
posted @ 2020-04-11 11:30  anweilx  阅读(210)  评论(0编辑  收藏  举报