Отказ от ответственности: я только начинаю с сборки x86. Я изучил немного SPIM в университете, но это вряд ли стоит упоминать.
Я думал, что начинаю с того, что, вероятно, самая простая функция в libc, abs(). Довольно просто в C:
long myAbs(long j) {
return j < 0 ? -j : j;
}
Моя версия в сборке:
.global myAbs
.type myAbs, @function
.text
myAbs:
test %rdi, %rdi
jns end
negq %rdi
end:
movq %rdi, %rax
ret
(Это не работает для 32-битных целых чисел, возможно, потому, что RAX - это 64-битный регистр, и знак, вероятно, находится в неправильном положении - я должен это расследовать).
Теперь вот что делает 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
Почему эта большая разница? GCC дает значительно больше инструкций. Я не могу себе представить, что это будет не медленнее, чем мой код. Я что-то упускаю? Или я делаю здесь что-то серьезное?