Disclaimer: Sono appena iniziato con l'assembly x86. Ho imparato un po 'di SPIM all'università, ma non vale la pena menzionarlo.Manual Assembly vs GCC
Ho pensato di iniziare con quella che probabilmente è la funzione più semplice in libc, abs(). Abbastanza semplice in C:
long myAbs(long j) {
return j < 0 ? -j : j;
}
La mia versione in assemblea:
.global myAbs
.type myAbs, @function
.text
myAbs:
test %rdi, %rdi
jns end
negq %rdi
end:
movq %rdi, %rax
ret
(Questo non funziona per gli interi a 32 bit, probabilmente perché RAX è un registro a 64 bit e il segno è probabilmente nella posizione sbagliata - Devo indagare su questo).
Ora qui è quello che fa gcc (GCC -O2 -S myAbs.c):
.file "myAbs.c"
.section .text.unlikely,"ax",@progbits
.LCOLDB0:
.text
.LHOTB0:
.p2align 4,,15
.globl myAbs
.type myAbs, @function
myAbs:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $4144, %rsp
orq $0, (%rsp)
addq $4128, %rsp
movq %rdi, %rdx
sarq $63, %rdx
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movq %rdi, %rax
xorq %rdx, %rax
subq %rdx, %rax
movq -8(%rbp), %rcx
xorq %fs:40, %rcx
jne .L5
leave
.cfi_remember_state
.cfi_def_cfa 7, 8
ret
.L5:
.cfi_restore_state
call [email protected]
.cfi_endproc
.LFE0:
.size myAbs, .-myAbs
.section .text.unlikely
.LCOLDE0:
.text
.LHOTE0:
.ident "GCC: (Gentoo Hardened 5.1.0 p1.2, pie-0.6.3) 5.1.0"
.section .note.GNU-stack,"",@progbits
Perché questa grande differenza? GCC produce sostanzialmente più istruzioni. Non riesco a immaginare che questo non sarà più lento del mio codice. Mi manca qualcosa? O sto facendo qualcosa di gravemente sbagliato qui?
Forse il tuo GCC non si sente male? Il mio produce [meno istruzioni] (https://goo.gl/wG2v1X). (E Clang ama [mosse condizionali] (https://goo.gl/xpxKyi).) –
"GCC: (Gentoo Hardened 5.1.0 p1.2, pie-0.6.3) 5.1.0" - Penso che questo sia la chiave. Il compilatore C rinforzato incorpora una protezione per lo smantellamento dello stack o qualcosa di simile. – davmac
Molte delle chiamate iniziali sono per impostare lo stack e salvare l'indirizzo di ritorno (cosa che non si sta facendo). Sembra che ci sia qualche protezione dello stack in corso.Forse è possibile ottimizzare le impostazioni del compilatore per sbarazzarsi di alcuni sovraccarichi. – carloabelli