1、C++源代码
1
2
3
4
5
6
7
8
9
10
| #include <iostream>
#include <cmath>
using namespace std;
int main(){
int a = 1;
int b = a++ + a++ + a++;
return 0;
} |
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int a = 1;
int b = a++ + a++ + a++;
return 0;
}
2、xCode中汇编结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| cplus`main:
0x100000f70 <+0>: pushq %rbp
0x100000f71 <+1>: movq %rsp, %rbp
0x100000f74 <+4>: xorl %eax, %eax
0x100000f76 <+6>: movl $0x0, -0x4(%rbp)
0x100000f7d <+13>: movl $0x1, -0x8(%rbp);设置局部变量(a=1)
;第一步(左运算值)%ecx
0x100000f84 <+20>: movl -0x8(%rbp), %ecx;取出变量值(1)[准备第一个+号左运算]
0x100000f87 <+23>: movl %ecx, %edx;准备第一次a++
0x100000f89 <+25>: addl $0x1, %edx;a++
0x100000f8c <+28>: movl %edx, -0x8(%rbp);第一次a++结果返回变量中(2)
;第二步(右运算值)%edx
0x100000f8f <+31>: movl -0x8(%rbp), %edx;取出第一次++的结果(2)[第一个+号右运算]
0x100000f92 <+34>: movl %edx, %esi;准备第二次a++
0x100000f94 <+36>: addl $0x1, %esi;a++
0x100000f97 <+39>: movl %esi, -0x8(%rbp);第二次a++结果返回变量中(3)
;第三步(第一个+运算)(返回值)%ecx
0x100000f9a <+42>: addl %edx, %ecx;运算第一个+号(1+2=3)[运算返回值,第二个+号的左运算值]
;第四步(右运算值)%edx
0x100000f9c <+44>: movl -0x8(%rbp), %edx;取出第二次a++后的结果(3)[第二个+号的右运算值]
0x100000f9f <+47>: movl %edx, %esi;准备第三次a++
0x100000fa1 <+49>: addl $0x1, %esi;a++
0x100000fa4 <+52>: movl %esi, -0x8(%rbp);第三次a++结果返回变量中(4)
;第五步(第二个+运算)(返回值)%ecx
0x100000fa7 <+55>: addl %edx, %ecx;运算第二个+号(3+3=6)[运算返回值]
;第六步(运算结束,赋值)
0x100000fa9 <+57>: movl %ecx, -0xc(%rbp);结果传给局部变量(c=6)
0x100000fac <+60>: popq %rbp
0x100000fad <+61>: retq |
cplus`main:
0x100000f70 <+0>: pushq %rbp
0x100000f71 <+1>: movq %rsp, %rbp
0x100000f74 <+4>: xorl %eax, %eax
0x100000f76 <+6>: movl $0x0, -0x4(%rbp)
0x100000f7d <+13>: movl $0x1, -0x8(%rbp);设置局部变量(a=1)
;第一步(左运算值)%ecx
0x100000f84 <+20>: movl -0x8(%rbp), %ecx;取出变量值(1)[准备第一个+号左运算]
0x100000f87 <+23>: movl %ecx, %edx;准备第一次a++
0x100000f89 <+25>: addl $0x1, %edx;a++
0x100000f8c <+28>: movl %edx, -0x8(%rbp);第一次a++结果返回变量中(2)
;第二步(右运算值)%edx
0x100000f8f <+31>: movl -0x8(%rbp), %edx;取出第一次++的结果(2)[第一个+号右运算]
0x100000f92 <+34>: movl %edx, %esi;准备第二次a++
0x100000f94 <+36>: addl $0x1, %esi;a++
0x100000f97 <+39>: movl %esi, -0x8(%rbp);第二次a++结果返回变量中(3)
;第三步(第一个+运算)(返回值)%ecx
0x100000f9a <+42>: addl %edx, %ecx;运算第一个+号(1+2=3)[运算返回值,第二个+号的左运算值]
;第四步(右运算值)%edx
0x100000f9c <+44>: movl -0x8(%rbp), %edx;取出第二次a++后的结果(3)[第二个+号的右运算值]
0x100000f9f <+47>: movl %edx, %esi;准备第三次a++
0x100000fa1 <+49>: addl $0x1, %esi;a++
0x100000fa4 <+52>: movl %esi, -0x8(%rbp);第三次a++结果返回变量中(4)
;第五步(第二个+运算)(返回值)%ecx
0x100000fa7 <+55>: addl %edx, %ecx;运算第二个+号(3+3=6)[运算返回值]
;第六步(运算结束,赋值)
0x100000fa9 <+57>: movl %ecx, -0xc(%rbp);结果传给局部变量(c=6)
0x100000fac <+60>: popq %rbp
0x100000fad <+61>: retq
3、如果对上述理解有一点难度,可以简化一下过程,因为都是a,所以容易绕晕,重点在于理解运算时,左运算数、右运算数准备到寄存器中,计算结果返回到相关变量中这一原则!!!
1
2
3
4
5
6
7
8
9
10
| #include <iostream>
#include <cmath>
using namespace std;
int main(){
int a = 1,b = 1,c = 1;
int d = a++ + b++ + c++;
return 0;
} |
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int a = 1,b = 1,c = 1;
int d = a++ + b++ + c++;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| cplus`main:
0x100000f60 <+0>: pushq %rbp
0x100000f61 <+1>: movq %rsp, %rbp
0x100000f64 <+4>: xorl %eax, %eax
0x100000f66 <+6>: movl $0x0, -0x4(%rbp)
0x100000f6d <+13>: movl $0x1, -0x8(%rbp)
0x100000f74 <+20>: movl $0x1, -0xc(%rbp)
0x100000f7b <+27>: movl $0x1, -0x10(%rbp)
0x100000f82 <+34>: movl -0x8(%rbp), %ecx;取出a【第1个+运算的左运算数】
0x100000f85 <+37>: movl %ecx, %edx
0x100000f87 <+39>: addl $0x1, %edx;a++
0x100000f8a <+42>: movl %edx, -0x8(%rbp);结果返回变量中
0x100000f8d <+45>: movl -0xc(%rbp), %edx;取出b【第1个+运算的右运算数】
0x100000f90 <+48>: movl %edx, %esi
0x100000f92 <+50>: addl $0x1, %esi;b++
0x100000f95 <+53>: movl %esi, -0xc(%rbp);结果返回变量中
0x100000f98 <+56>: addl %edx, %ecx;执行第1个+运算(1+1=2)【第2个+运算的左运算数】
0x100000f9a <+58>: movl -0x10(%rbp), %edx;取出c【第2个+运算的右运算数】
0x100000f9d <+61>: movl %edx, %esi
0x100000f9f <+63>: addl $0x1, %esi;c++
0x100000fa2 <+66>: movl %esi, -0x10(%rbp);结果返回变量中
0x100000fa5 <+69>: addl %edx, %ecx;执行第2个+运算(2+1=3)
0x100000fa7 <+71>: movl %ecx, -0x14(%rbp);结果返回变量中
0x100000faa <+74>: popq %rbp
0x100000fab <+75>: retq |
cplus`main:
0x100000f60 <+0>: pushq %rbp
0x100000f61 <+1>: movq %rsp, %rbp
0x100000f64 <+4>: xorl %eax, %eax
0x100000f66 <+6>: movl $0x0, -0x4(%rbp)
0x100000f6d <+13>: movl $0x1, -0x8(%rbp)
0x100000f74 <+20>: movl $0x1, -0xc(%rbp)
0x100000f7b <+27>: movl $0x1, -0x10(%rbp)
0x100000f82 <+34>: movl -0x8(%rbp), %ecx;取出a【第1个+运算的左运算数】
0x100000f85 <+37>: movl %ecx, %edx
0x100000f87 <+39>: addl $0x1, %edx;a++
0x100000f8a <+42>: movl %edx, -0x8(%rbp);结果返回变量中
0x100000f8d <+45>: movl -0xc(%rbp), %edx;取出b【第1个+运算的右运算数】
0x100000f90 <+48>: movl %edx, %esi
0x100000f92 <+50>: addl $0x1, %esi;b++
0x100000f95 <+53>: movl %esi, -0xc(%rbp);结果返回变量中
0x100000f98 <+56>: addl %edx, %ecx;执行第1个+运算(1+1=2)【第2个+运算的左运算数】
0x100000f9a <+58>: movl -0x10(%rbp), %edx;取出c【第2个+运算的右运算数】
0x100000f9d <+61>: movl %edx, %esi
0x100000f9f <+63>: addl $0x1, %esi;c++
0x100000fa2 <+66>: movl %esi, -0x10(%rbp);结果返回变量中
0x100000fa5 <+69>: addl %edx, %ecx;执行第2个+运算(2+1=3)
0x100000fa7 <+71>: movl %ecx, -0x14(%rbp);结果返回变量中
0x100000faa <+74>: popq %rbp
0x100000fab <+75>: retq
4、索性再来一个++a的吧
4.1、C++及AT&A汇编
1
2
3
4
5
6
7
8
9
10
| #include <iostream>
#include <cmath>
using namespace std;
int main(){
int a = 1,b = 1,c = 1;
int d = ++a + ++a + ++a;
return 0;
} |
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int a = 1,b = 1,c = 1;
int d = ++a + ++a + ++a;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| cplus`main:
0x100000f70 <+0>: pushq %rbp
0x100000f71 <+1>: movq %rsp, %rbp
0x100000f74 <+4>: xorl %eax, %eax
0x100000f76 <+6>: movl $0x0, -0x4(%rbp)
0x100000f7d <+13>: movl $0x1, -0x8(%rbp)
0x100000f84 <+20>: movl $0x1, -0xc(%rbp)
0x100000f8b <+27>: movl $0x1, -0x10(%rbp)
;第1个a++
0x100000f92 <+34>: movl -0x8(%rbp), %ecx
0x100000f95 <+37>: addl $0x1, %ecx
0x100000f98 <+40>: movl %ecx, -0x8(%rbp)
;第2个a++
0x100000f9b <+43>: movl -0x8(%rbp), %edx
0x100000f9e <+46>: addl $0x1, %edx
0x100000fa1 <+49>: movl %edx, -0x8(%rbp)
;(a++)+(a++)
0x100000fa4 <+52>: addl %edx, %ecx
;第3个a++
0x100000fa6 <+54>: movl -0x8(%rbp), %edx
0x100000fa9 <+57>: addl $0x1, %edx
0x100000fac <+60>: movl %edx, -0x8(%rbp)
;((a++)+(a++))+(a++)
0x100000faf <+63>: addl %edx, %ecx
;返回值
0x100000fb1 <+65>: movl %ecx, -0x14(%rbp)
0x100000fb4 <+68>: popq %rbp
0x100000fb5 <+69>: retq |
cplus`main:
0x100000f70 <+0>: pushq %rbp
0x100000f71 <+1>: movq %rsp, %rbp
0x100000f74 <+4>: xorl %eax, %eax
0x100000f76 <+6>: movl $0x0, -0x4(%rbp)
0x100000f7d <+13>: movl $0x1, -0x8(%rbp)
0x100000f84 <+20>: movl $0x1, -0xc(%rbp)
0x100000f8b <+27>: movl $0x1, -0x10(%rbp)
;第1个a++
0x100000f92 <+34>: movl -0x8(%rbp), %ecx
0x100000f95 <+37>: addl $0x1, %ecx
0x100000f98 <+40>: movl %ecx, -0x8(%rbp)
;第2个a++
0x100000f9b <+43>: movl -0x8(%rbp), %edx
0x100000f9e <+46>: addl $0x1, %edx
0x100000fa1 <+49>: movl %edx, -0x8(%rbp)
;(a++)+(a++)
0x100000fa4 <+52>: addl %edx, %ecx
;第3个a++
0x100000fa6 <+54>: movl -0x8(%rbp), %edx
0x100000fa9 <+57>: addl $0x1, %edx
0x100000fac <+60>: movl %edx, -0x8(%rbp)
;((a++)+(a++))+(a++)
0x100000faf <+63>: addl %edx, %ecx
;返回值
0x100000fb1 <+65>: movl %ecx, -0x14(%rbp)
0x100000fb4 <+68>: popq %rbp
0x100000fb5 <+69>: retq
4.2、8086汇编
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| assume ss:stack, ds:data, cs:code
stack segment
db 20h dup(0cch)
stack ends
data segment
db 20h dup(0cch)
data ends
code segment
start:
mov ax, stack
mov ss, ax
mov sp, 20h
mov ax, data
mov ds, ax
push bp
mov bp, sp
sub sp, 10h
;------业务代码----Begain
;int a = 1;
;int b = ++a + ++a + ++a;
mov word ptr [bp-2], 1h
;第1个++运算【第1个+左运算数】
mov ax, [bp-2]
add ax, 1h
mov word ptr [bp-2], ax
;第2个++运算【第1个+右运算数】
mov bx, [bp-2]
add bx,1h
mov word ptr [bp-2], bx
add ax, bx;第1个+运算【第2个+左运算数】
;第3个++运算【第2个+右运算数】
mov bx, [bp-2]
add bx, 1h
mov word ptr [bp-2], bx
add ax, bx;第2个+运算【返回值,或下一个左运算数】
mov word ptr [bp-4], ax;返回值赋给b
;------业务代码----End
;Exit
mov ah, 4ch
int 21h
code ends
end start |
assume ss:stack, ds:data, cs:code
stack segment
db 20h dup(0cch)
stack ends
data segment
db 20h dup(0cch)
data ends
code segment
start:
mov ax, stack
mov ss, ax
mov sp, 20h
mov ax, data
mov ds, ax
push bp
mov bp, sp
sub sp, 10h
;------业务代码----Begain
;int a = 1;
;int b = ++a + ++a + ++a;
mov word ptr [bp-2], 1h
;第1个++运算【第1个+左运算数】
mov ax, [bp-2]
add ax, 1h
mov word ptr [bp-2], ax
;第2个++运算【第1个+右运算数】
mov bx, [bp-2]
add bx,1h
mov word ptr [bp-2], bx
add ax, bx;第1个+运算【第2个+左运算数】
;第3个++运算【第2个+右运算数】
mov bx, [bp-2]
add bx, 1h
mov word ptr [bp-2], bx
add ax, bx;第2个+运算【返回值,或下一个左运算数】
mov word ptr [bp-4], ax;返回值赋给b
;------业务代码----End
;Exit
mov ah, 4ch
int 21h
code ends
end start
8086汇编版本二(完整版):
1、一元运算与二元运算均统一步骤:取值–>运算–>回写
1.1、取第1次+左运算数到ax【第1次+左运算数】(取值a=1)
1.2、准备执行第1次++操作,在bx中完成,运算完成后回写到变量中【第1次+左运算数++】
1.3、取第1次+右运算数到bx【第1次+右运算数】(取值a=2)
1.4、准备执行第2次++操作,在cx中完成,运算完成后回写到变量中【第1次+右运算数++】(a=3)
1.5、执行第1次+运算,运算结果返回在ax中【第2次+左运算数】(1+2=3)
1.6、取第2次+右运算数到bx【第2次+右运算数】(a=3)
1.7、准备执行第3次++操作,在cx中完成,运算完成后回写到变量中(a=4)
1.8、执行第2次+运算,运算结果返回在ax中(3+3=6)
1.9、返回结果存在变量中(b=6)
8086汇编版本一(简化版):
1、ax、bx两个寄存器分别存储运算的左运算数与右运算数
2、运算基本步骤(后置++的优先级小于+运算,因此左运算数在运算前不能自加)
2.1、取a的值到ax寄存器(1)【第1个+的左运算数】
2.2、取a的值到bx寄存器(1)
2.3、执行第1次a++运算,直接bx寄存器+1(2)【第1个+的右运算数】
2.4、执行第1个+运算,结果返回到ax寄存器(1+2=3)【返回值】【第2个+的左运算数】
2.5、执行第2次a++运算,直接bx寄存器+1(3)【第2个+的右运算数】
2.6、执行第2个+运算,结果返回到ax寄存器(3+3=6)【返回值】
2.7、执行第3次a++运算,直接bx寄存器+1(4)