#include <stdio.h> int main(int argc, const char *argv[]) { int a; scanf("%d", &a); if (a + 1 == a) { printf("bad!:(\n"); } else { printf("good!:)\n"); } return 0; }
.file "deadloop1.c" .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "%d" .LC1: .string "good!:)" .text .p2align 4,,15 .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp leal 28(%esp), %eax movl %eax, 4(%esp) movl $.LC0, (%esp) call __isoc99_scanf movl $.LC1, (%esp) call puts xorl %eax, %eax leave ret .size main, .-main .ident "GCC: (Debian 4.4.5-8) 4.4.5" .section .note.GNU-stack,"",@progbits
#include <stdio.h> int inc(int num) { return num + 1; } int main(int argc, const char *argv[]) { int a; scanf("%d", &a); if (a + 1 == inc(a)) { printf("good!:)\n"); } else { printf("bad!:(\n"); } return 0; }
.file "deadloop.c" .text .p2align 4,,15 .globl inc .type inc, @function inc: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax popl %ebp addl $1, %eax ret .size inc, .-inc .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "%d" .LC1: .string "good!:)" .text .p2align 4,,15 .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp leal 28(%esp), %eax movl %eax, 4(%esp) movl $.LC0, (%esp) call __isoc99_scanf movl $.LC1, (%esp) call puts xorl %eax, %eax leave ret .size main, .-main .ident "GCC: (Debian 4.4.5-8) 4.4.5" .section .note.GNU-stack,"",@progbits
#include <stdio.h> int __attribute__((noinline))inc(int num) { return num + 1; } int main(int argc, const char *argv[]) { int a; scanf("%d", &a); if (a + 1 == inc(a)) { printf("good!:)\n"); } else { printf("bad!:(\n"); } return 0; }
.file "deadloop.c" .text .p2align 4,,15 .globl inc .type inc, @function inc: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax popl %ebp addl $1, %eax ret .size inc, .-inc .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "%d" .LC1: .string "good!:)" .LC2: .string "bad!:(" .text .p2align 4,,15 .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp pushl %ebx subl $44, %esp leal 28(%esp), %eax movl %eax, 4(%esp) movl $.LC0, (%esp) call __isoc99_scanf movl 28(%esp), %ebx movl %ebx, (%esp) addl $1, %ebx call inc cmpl %eax, %ebx je .L8 movl $.LC2, (%esp) call puts addl $44, %esp xorl %eax, %eax popl %ebx movl %ebp, %esp popl %ebp ret .p2align 4,,7 .p2align 3 .L8: movl $.LC1, (%esp) call puts addl $44, %esp xorl %eax, %eax popl %ebx movl %ebp, %esp popl %ebp ret .size main, .-main .ident "GCC: (Debian 4.4.5-8) 4.4.5" .section .note.GNU-stack,"",@progbits
#include <stdio.h> #include <unistd.h> #include <time.h> int main(int argc, const char *argv[]) { time_t t1, t2; time(&t1); sleep(3); time(&t2); if (t1 != t2) { printf("good!:)\n"); } else { printf("bad!:(\n"); } return 0; }
.file "deadloop2.c" .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "good!:)" .LC1: .string "bad!:(" .text .p2align 4,,15 .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp leal 28(%esp), %eax movl %eax, (%esp) call time movl $3, (%esp) call sleep leal 24(%esp), %eax movl %eax, (%esp) call time movl 28(%esp), %eax cmpl 24(%esp), %eax je .L2 movl $.LC0, (%esp) call puts xorl %eax, %eax leave ret .p2align 4,,7 .p2align 3 .L2: movl $.LC1, (%esp) call puts xorl %eax, %eax leave ret .size main, .-main .ident "GCC: (Debian 4.4.5-8) 4.4.5" .section .note.GNU-stack,"",@progbits
非常遗憾,对于这个逻辑可能是因为调用外部的库或者受这个程序外部因素影响太大,无法再进行优化了。
本次测试用的GCC版本为4.4.5,操作系统为GNU/Linux,优化选项均为-O3。
上面说到的一般情况我是这么理解的,比如a == a并不一定是一个原子操作,就这么简单一个逻辑表达式可能经历的操作是先把a的值从内存放入寄存器1,再把b的值放入寄存器2,再进行比较,其间寄存器和内存的值都有可能被别的进程或线程打断并设法修改。不过很明显,如果连a == a都无法确定,那么编译器的优化手段几乎无从下手了,因为你什么都无法确定。