Semua jawaban sangat bagus. Tetapi di atas itu, saya ingin membagikan sebuah contoh.
Di bawah ini adalah program cpp kecil:
#include <iostream>
int x;
int main(){
char buf[50];
x = 8;
if(x == 8)
printf("x is 8\n");
else
sprintf(buf, "x is not 8\n");
x=1000;
while(x > 5)
x--;
return 0;
}
Sekarang, mari kita hasilkan perakitan kode di atas (dan saya hanya akan menempelkan bagian-bagian dari perakitan yang relevan di sini):
Perintah untuk menghasilkan perakitan:
g++ -S -O3 -c -fverbose-asm -Wa,-adhln assembly.cpp
Dan majelis:
main:
.LFB1594:
subq $40, %rsp #,
.seh_stackalloc 40
.seh_endprologue
# assembly.cpp:5: int main(){
call __main #
# assembly.cpp:10: printf("x is 8\n");
leaq .LC0(%rip), %rcx #,
# assembly.cpp:7: x = 8;
movl $8, x(%rip) #, x
# assembly.cpp:10: printf("x is 8\n");
call _ZL6printfPKcz.constprop.0 #
# assembly.cpp:18: }
xorl %eax, %eax #
movl $5, x(%rip) #, x
addq $40, %rsp #,
ret
.seh_endproc
.p2align 4,,15
.def _GLOBAL__sub_I_x; .scl 3; .type 32; .endef
.seh_proc _GLOBAL__sub_I_x
Anda dapat melihat dalam rakitan bahwa kode rakitan tidak dibuat sprintf
karena kompiler berasumsi bahwa x
tidak akan berubah di luar program. Dan sama halnya dengan while
loop. while
loop sama sekali dihapus karena optimasi karena kompilator melihatnya sebagai kode yang tidak berguna dan dengan demikian langsung ditugaskan 5
ke x
(lihat movl $5, x(%rip)
).
Masalahnya terjadi ketika bagaimana jika proses / perangkat keras eksternal akan mengubah nilai x
suatu tempat antara x = 8;
dan if(x == 8)
. Kami berharap else
blok berfungsi, tetapi sayangnya kompiler telah memangkas bagian itu.
Sekarang, untuk menyelesaikan ini, di assembly.cpp
, mari kita ubah int x;
untuk volatile int x;
dan cepat melihat kode assembly yang dihasilkan:
main:
.LFB1594:
subq $104, %rsp #,
.seh_stackalloc 104
.seh_endprologue
# assembly.cpp:5: int main(){
call __main #
# assembly.cpp:7: x = 8;
movl $8, x(%rip) #, x
# assembly.cpp:9: if(x == 8)
movl x(%rip), %eax # x, x.1_1
# assembly.cpp:9: if(x == 8)
cmpl $8, %eax #, x.1_1
je .L11 #,
# assembly.cpp:12: sprintf(buf, "x is not 8\n");
leaq 32(%rsp), %rcx #, tmp93
leaq .LC0(%rip), %rdx #,
call _ZL7sprintfPcPKcz.constprop.0 #
.L7:
# assembly.cpp:14: x=1000;
movl $1000, x(%rip) #, x
# assembly.cpp:15: while(x > 5)
movl x(%rip), %eax # x, x.3_15
cmpl $5, %eax #, x.3_15
jle .L8 #,
.p2align 4,,10
.L9:
# assembly.cpp:16: x--;
movl x(%rip), %eax # x, x.4_3
subl $1, %eax #, _4
movl %eax, x(%rip) # _4, x
# assembly.cpp:15: while(x > 5)
movl x(%rip), %eax # x, x.3_2
cmpl $5, %eax #, x.3_2
jg .L9 #,
.L8:
# assembly.cpp:18: }
xorl %eax, %eax #
addq $104, %rsp #,
ret
.L11:
# assembly.cpp:10: printf("x is 8\n");
leaq .LC1(%rip), %rcx #,
call _ZL6printfPKcz.constprop.1 #
jmp .L7 #
.seh_endproc
.p2align 4,,15
.def _GLOBAL__sub_I_x; .scl 3; .type 32; .endef
.seh_proc _GLOBAL__sub_I_x
Di sini Anda dapat melihat bahwa kode perakitan untuk sprintf
, printf
dan while
loop dihasilkan. Keuntungannya adalah jika x
variabel diubah oleh beberapa program eksternal atau perangkat keras, sprintf
bagian dari kode akan dieksekusi. Dan juga demikianwhile
loop dapat digunakan untuk menunggu sibuk sekarang.