По сути, нет: он использует больше кода и больше инструкций, чтобы сказать то же самое.
Обычно это указывает на одну из двух вещей:
- кого-то, кто не оченьудобен код C
- , где кто-то планировал сделать что-то большее с отрицательным возвратом, например, записать сообщение об ошибке, но не сделал этого.
Хм.В данном случае это может указывать код переведенный механически, скажем, Fortran.
1012 *
Обновлены снова 1016 * Хорошо, так что это еще спорный.Вот реальный пример.Обратите внимание, что пример точно изоморфен примеру OP:
C-код:
int retcod1() { return 0; }
int ex1(){
if(retcod1())
return 0;
else
return 1;
}
int ex2() {
return retcod1();
}
Генерируемая сборка:
Этот код сгенерирован с помощью gcc -S -O0
:
.file "code.c"
.text
.globl retcod1
.type retcod1, @function
retcod1:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size retcod1, .-retcod1
.globl ex1
.type ex1, @function
ex1:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movl $0, %eax
call retcod1
testl %eax, %eax
je .L3
movl $0, %eax
jmp .L4
.L3:
movl $1, %eax
.L4:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size ex1, .-ex1
.globl ex2
.type ex2, @function
ex2:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movl $0, %eax
call retcod1
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size ex2, .-ex2
.ident "GCC: (SUSE Linux) 4.5.1 20101208 [gcc-4_5-branch revision 167585]"
.section .comment.SUSE.OPTs,"MS",@progbits,1
.string "ospwg"
.section .note.GNU-stack,"",@progbits
Для удобства (если SO может обрабатывать формат), я взял сгенерированный код длядве процедуры и положить их рядом.Заметьте, что второй пример значительно короче.
.globl ex1 .globl ex2
.type ex1, @function .type ex2, @function
ex1: ex2:
.LFB1: .LFB2:
.cfi_startproc .cfi_startproc
pushq %rbp pushq %rbp
.cfi_def_cfa_offset 16 .cfi_def_cfa_offset 16
movq %rsp, %rbp movq %rsp, %rbp
.cfi_offset 6, -16 .cfi_offset 6, -16
.cfi_def_cfa_register 6 .cfi_def_cfa_register 6
movl $0, %eax movl $0, %eax
call retcod1 call retcod1
testl %eax, %eax leave
je .L3 .cfi_def_cfa 7, 8
movl $0, %eax ret
jmp .L4 .cfi_endproc
.L3: .LFE2:
movl $1, %eax
.L4:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size ex1, .-ex1
Вот пример с оптимизацией по умолчанию, то есть gcc -S
:
ex1: ex2:
.LFB1: .LFB2:
.cfi_startproc .cfi_startproc
pushq %rbp pushq %rbp
.cfi_def_cfa_offset 16 .cfi_def_cfa_offset 16
movq %rsp, %rbp movq %rsp, %rbp
.cfi_offset 6, -16 .cfi_offset 6, -16
.cfi_def_cfa_register 6 .cfi_def_cfa_register 6
movl $0, %eax movl $0, %eax
call retcod1 call retcod1
testl %eax, %eax leave
je .L3 .cfi_def_cfa 7, 8
movl $0, %eax ret
jmp .L4 .cfi_endproc
.L3: .LFE2:
movl $1, %eax .size ex2, .-ex2
.L4:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size ex1, .-ex1
.globl ex2
.type ex2, @function
Опять же, все еще значительнокороче.
Наконец, вот пример, на этот раз с full оптимизацией:
.globl ex1 .globl ex2
.type ex1, @function .type ex2, @function
ex1: ex2:
.LFB1: .LFB2:
.cfi_startproc .cfi_startproc
movl $1, %eax xorl %eax, %eax
ret ret
.cfi_endproc .cfi_endproc
.LFE1: .LFE2:
Теперь обратите внимание, что даже при полной оптимизации он все еще не создает точно того же кода, который был заявлен.