标签:汇编 变量 eax int 累加 关键字 add volatile 内存
两个示例函数,循环对一个全局变量(c和d)进行累加计算,其中变量c有volatile关键字修饰,变量c没有。使用gcc O2优化编译后,使用objdump导出汇编。
从汇编代码看出,add函数被编译优化,内存变量d首先被放到了寄存器EAX,后续所有的累加操作,都是对EAX中值的累加,循环计算完成后,最后EAX结果写入内存变量d()。
addx函数没有被优化,循环中每一次累加前从内存变量c读取写入EAX,计算后再都被写入内存变量c(11c0),再从内存变量C读出放入EAX,做下一步循环计算。
两者比较之下,add对内存变量d的读写各只有1次,addx则在每次循环都有一次对变量c的读写操作,显然addx的性能会因此差很多。
但在多线程程序中,在循环累加的过程中,如果有另一个线程读取变量c和d,那么对于c变量可以获取到每一步循环的累加的中间值。而对于变量d,只会获取到初始值,直到add循环结束后才能获取到最终结果。
因此,在多线程并发程序中,共享变量最好加上volatile,特别是当这个变量在一个线程的逻辑过程中会多次变更,而另一个线程需要获取这个变量的实时状态时,否者可能只会获取到的该变量值可能已经过期。如果对于共享变量值的实时性并没有要求,则volatile并非必须。
volatile int c = 0;
int d = 0;
void add(int a, int b ) {
while ( d < 100 ) d = d + a + b;
}
void addx(int a, int b ) {
while ( c < 100 ) c = c + a + b;
}
0000000000001190 <add>:
1190: endbr64
1194: mov 0x2e7a(%rip),%eax # 4014 <d>
119a: cmp $0x63,%eax
119d: jg 11af <add+0x1f>
119f: nop
11a0: add %esi,%eax
11a2: add %edi,%eax
11a4: cmp $0x63,%eax
11a7: jle 11a0 <add+0x10>
11a9: mov %eax,0x2e65(%rip) # 4014 <d>
11af: retq
00000000000011b0 <addx>:
11b0: endbr64
11b4: jmp 11d0 <addx+0x20>
11b6: nopw %cs:0x0(%rax,%rax,1)
11bd: 00 00 00
11c0: mov 0x2e52(%rip),%eax # 4018 <c>
11c6: add %edi,%eax
11c8: add %esi,%eax
11ca: mov %eax,0x2e48(%rip) # 4018 <c>
11d0: mov 0x2e42(%rip),%eax # 4018 <c>
11d6: cmp $0x63,%eax
11d9: jle 11c0 <addx+0x10>
11db: retq
11dc: nopl 0x0(%rax)
标签:汇编,变量,eax,int,累加,关键字,add,volatile,内存 来源: https://blog.csdn.net/luckysym/article/details/119151270
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。