首页 >> 民生杂谈

程序的机器级表示

民生杂谈  2021-08-24 13:29 字号: 大 中 小

switch和ifelse的组合是不同的,不仅仅是代码看上去更清晰。

/////////////// C CODE /////////////////

// filename:asm05.c

/*show the switch*/

void fun_switch(int x)

{

int a;

switch(x)

{

case 10:

a=x;

break;

case 12:

a=x-2;

break;

case 16:

a=x-10;

case 18:

a--;

break;

case 19:

case 20:

a=10;

break;

default:

a=0;

}

}

/////////////// ASM CODE ////////////////

// command : gcc -S asm06.c

.file\"asm06.c\"

.text

.globl _fun_switch

.def_fun_switch;.scl2;.type32;.endef

_fun_switch:

pushl%ebp

movl%esp, %ebp

subl$8, %esp

movl8(%ebp), %eax

subl$10, %eax

movl%eax, -8(%ebp)

cmpl$10, -8(%ebp)

jaL9

movl-8(%ebp), %edx

movlL10(,%edx,4), %eax

jmp*%eax

.section .rdata,\"dr\"

.align 4

刘志军还涉嫌帮助女商人丁书苗非法获利30亿余元。 L10:

.longL3

.longL9

.longL4

.longL9

.longL9

.longL9

.longL5

.longL9

.longL6

.longL8

.longL8

.text

L3:

movl8(%ebp), %eax

movl%eax, -4(%ebp)

jmpL1

L4:

movl8(%ebp), %eax

subl$2, %eax

movl%eax, -4(%ebp)

jmpL1

L5:

movl8(%ebp), %eax

subl$10, %eax

movl%eax, -4(%ebp)

L6:

leal-4(%ebp), %eax

decl(%eax)

jmpL1

L8:

movl$10, -4(%ebp)

jmpL1

L9:

movl$0, -4(%ebp)

L1:

leave

ret

上面的汇编表示中有这样一段语句:

.section .rdata,\"dr\"

.align 4

L10:

.longL3;case 10

.longL9;default

.longL4;case 12

.longL9;default

.longL9;default

.longL9;default

.longL5;case 16

.longL9;default

.longL6;case 18

.longL8;case 19

.longL8;case 20

.text

这就是我们所谓的跳转表,它表示了一个相对的偏移,我们的最大值-最小值+default=11。

cmpl$10, -8(%ebp)

jaL9

movl-8(%ebp), %edx

movlL10(,%edx,4), %eax

这里我们拿x和10的差与偏移数(10)做比较,并按照跳转表中的表示,跳转到相应的位置去。所以它的执行效率

比较高。

当然,也不是总是这么理想化,我们对于switch的值如果比较紧凑可以很好的利用switch的优势,但是如果数

值跨度比较大,那么switch就不会使用跳转表了,比如我们把asm06.c中的最后一个条件case 20:改为case

2000: 那么,编译器会把它编译成为类似ifelse组合的形式:

/////////////// ASM CODE ////////////////

// command : gcc -S asm06.c

.file\"asm06.c\"

.text

.globl _fun_switch

.def_fun_switch;.scl2;.type32;.endef

_fun_switch:

pushl%ebp

movl%esp, %ebp

subl$8, %esp

movl8(%ebp), %eax

movl%eax, -8(%ebp)

cmpl$16, -8(%ebp)

jeL5

cmpl$16, -8(%ebp)

jgL10

cmpl$10, -8(%ebp)

jeL3

cmpl$12, -8(%ebp)

jeL4

jmpL9

L10:

cmpl$19, -8(%ebp)

jeL8

cmpl$19, -8(%ebp)

jgL11

cmpl$18, -8(%ebp)

jeL6

jmpL9

L11:

cmpl$2000, -8(%ebp)

jeL8

jmpL9

L3:

movl8(%ebp), %eax

movl%eax, -4(%ebp)

jmpL1

L4:

movl8(%ebp), %eax

subl$2, %eax

movl%eax, -4(%ebp)

jmpL1

L5:

movl8(%ebp), %eax

subl$10, %eax

movl%eax, -4(%ebp)

L6:

leal-4(%ebp), %eax

decl(%eax)

jmpL1

L8:

movl$10, -4(%ebp)

jmpL1

L9:

movl$0, -4(%ebp)

L1:

leave

ret

////////////////////////////////

// 继续充电

////////////////////////////////

发现我也只能说到这里,再深入,还需要我继续修炼...希望能给初学C语言的朋友一些引导性的信息。没准儿

上海男性功能障碍哪家好
武汉盆腔炎
杭州不孕不育医院治疗
推荐资讯