我土星了,GCC比CSAPP里说的更聪明了,对switch程序编译不用跳转表了。
对比VC2008和gcc给出的汇编代码,能发现VC倒还在用跳转表,gcc的汇编代码由于不用跳转表,更小更紧凑,却也更难读了。
C程序
int switchfunc(int x) { int result = 100; switch (x) { case 100: result += 0; break; case 101: result += 1; break; case 102: result += 2; case 103: result += 3; break; default: // we do nothing
; } return result; }
|
VC 2008 编译版本
ASM不是很会,不过看得出来是按照跳转表编译的。
PUBLIC _switchfunc ; Function compile flags: /Ogtpy ; File e:\cpp\switch.c _TEXT SEGMENT _x$ = 8 ; size = 4 _switchfunc PROC
; 3 : int result = 100; ; 4 : switch (x)
mov ecx, DWORD PTR _x$[esp-4] add ecx, -100 ; ffffff9cH mov eax, 100 ; 00000064H cmp ecx, 3 ja SHORT $LN1@switchfunc jmp DWORD PTR $LN10@switchfunc[ecx*4] $LN4@switchfunc:
; 5 : { ; 6 : case 100: ; 7 : result += 0; ; 8 : break; ; 9 : ; 10 : case 101: ; 11 : result += 1;
mov eax, 101 ; 00000065H
; 19 : break; ; 20 : ; 21 : default: // we do nothing ; 22 : ; ; 23 : } ; 24 : return result; ; 25 : }
ret 0 $LN3@switchfunc:
; 12 : break; ; 13 : ; 14 : case 102: ; 15 : result += 2;
mov eax, 102 ; 00000066H $LN2@switchfunc:
; 16 : ; 17 : case 103: ; 18 : result += 3;
add eax, 3 $LN1@switchfunc:
; 19 : break; ; 20 : ; 21 : default: // we do nothing ; 22 : ; ; 23 : } ; 24 : return result; ; 25 : }
ret 0 npad 1 $LN10@switchfunc: DD $LN1@switchfunc DD $LN4@switchfunc DD $LN3@switchfunc DD $LN2@switchfunc _switchfunc ENDP _TEXT ENDS END
|
Linux GCC编译版本
gcc做了不少很聪明的优化。就像看到102不break跳到103,gcc直接把105赋值给%eax。
而且怎么没看到上来就赋值100给%eax呢?
switchfunc: pushl %ebp movl $105, %eax movl %esp, %ebp movl 8(%ebp), %edx cmpl $102, %edx je .L6 cmpl $103, %edx movb $103, %al je .L6 xorl %eax, %eax cmpl $101, %edx sete %al addl $100, %eax // 答案就在这里 .L6: popl %ebp ret
|
阅读(1782) | 评论(0) | 转发(0) |