c语言什么叫对应语句,c语言控制语句对应的汇编语句代码

本文详细解析了C语言中的if-then、do-while、while、for和switch语句,并展示了它们对应的汇编代码实现。通过具体示例,阐述了这些基本流程控制结构如何被编译器转化为低级机器指令,强调了跳转表在switch语句中的高效作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、if-then

if-then语句的通用形式为:

if (test-expr)

then-statement

else

else-statement

这里的test-expr是整型表达式,它的取值为0或者为非0。

if-then语句对应的汇编实现形式为:

t = test-expr;

if (t)

goto true;

else-statement

goto done;

ture:

then-statement

done:

下面通过一个例子说明:

/* $begin absdiff-c */

int absdiff(int x, int y)

{

if (x < y)

return y - x;

else

return x - y;

}

/* $end absdiff-c */

查看gcc生成的汇编代码可以看到如下代码:

movl    8(%ebp), %edx        ;x->edx

movl    12(%ebp), %eax    ;y->eax

cmpl    %eax, %edx            ;x-y

jge     .L2                    ;if(x>=y) then goto .L2

popl    %ebp                    ;reset frame pointer

subl    %edx, %eax            ;then-statement(take care!)

ret                                ;return (always put the return value in eax)

.p2align 4,,7                ;why? I don't know!

.L2:                                        ;else-part

popl    %ebp                    ;reset frame pointer

subl    %eax, %edx            ;else-statement

movl    %edx, %eax

ret                                ;return

2、do-while

do-while语句的通用形式为:

do

body-statement

while(test-expr);

注意:body-statement至少执行一次。

该语句对应的汇编实现形式为:

loop:

body-statement

t = test-expr;

if(t)

goto loop;

下面通过一个例子加深理解:

/* $begin fibdw-c */

int fib_dw(int n)

{

int i = 0;

int val = 0;

int nval = 1;

do {

int t = val + nval;

val = nval;

nval = t;

i++;

} while (i < n);

return val;

}

/* $end fibdw-c */

查看其对应的汇编代码如下:

subl    $16, %esp            ;for local variables:t->nval->val->i

movl    $0, -16(%ebp)        ;i = 0

movl    $0, -12(%ebp)        ;val = 0

movl    $1, -8(%ebp)        ;nval = 1

.L2:

movl    -8(%ebp), %eax    ;nval->eax

addl    -12(%ebp), %eax    ;val+nval->eax

movl    %eax, -4(%ebp)    ;eax->t

movl    -8(%ebp), %eax    ;nval->eax

movl    %eax, -12(%ebp)    ;eax->val

movl    -4(%ebp), %eax    ;t->eax

movl    %eax, -8(%ebp)    ;eax->nval

addl    $1, -16(%ebp)        ;i++

movl    -16(%ebp), %eax    ;i->eax

cmpl    8(%ebp), %eax        ;i-n

jl      .L2                    ;if (i

movl    -12(%ebp), %eax    ;return val

3、while语句

while语句的通用形式为:

while(test-expr)

body-statement

直接翻译成使用goto语句的形式为:

loop:

t = test-expr;

if(!t)

goto done;

body-statement

goto loop

done:

由于这样的翻译要求内循环,大多说c编译器将这段代码转换成do-while循环。

t = test-expr

if(!t)

goto done;

loop:

body-statement

t = test-expr;

if(t)

goto loop;

done:

或者:

goto L

loop:

body-statement

L:

t = test-expr

if(t)

goto loop

举个例子:

/* $begin fibw-c */

int fib_w(int n)

{

int i = 1;

int val = 1;

int nval = 1;

while (i < n) {

int t = val+nval;

val = nval;

nval = t;

i++;

}

return val;

}

/* $end fibw-c */

对应的汇编代码如下:

subl    $16, %esp            ;for local variables:t->nval->val->i

movl    $1, -16(%ebp)        ;i = 1

movl    $1, -12(%ebp)        ;val = 1

movl    $1, -8(%ebp)        ;nval = 1

jmp     .L6

.L7:                                        ;body-statement

movl    -8(%ebp), %eax    ;nval->eax

addl    -12(%ebp), %eax    ;nval+val->eax

movl    %eax, -4(%ebp)    ;eax->t

movl    -8(%ebp), %eax    ;nal->eax

movl    %eax, -12(%ebp)    ;eax->val

movl    -4(%ebp), %eax    ;t->eax

movl    %eax, -8(%ebp)    ;eax->nval

addl    $1, -16(%ebp)        ;i++

.L6:

movl    -16(%ebp), %eax    ;i->eax

cmpl    8(%ebp), %eax        ;i-n

jl      .L7                    ;if(i

movl    -12(%ebp), %eax    ;return value

4、for语句

for语句的通用形式为:

for(init-expr;test-expr;update-expr)

body-statement

for语句的语义可以用while语句表示:

init-expr;

while (test-expr) {

body-statement

update-expr;

}

这样就可以根据前面的while语句的翻译来实现for语句的翻译:

init-expr;

goto L;

loop:

body-statement

update-expr;

L:

t = test-expr;

if(t)

goto loop

for example:

/* $begin fibf-c */

int fib_f(int n)

{

int i;

int val = 1;

int nval = 1;

for (i = 1; i < n; i++) {

int t = val+nval;

val = nval;

nval = t;

}

return val;

}

/* $end fibf-c */

对应汇编代码:

subl    $16, %esp            ;for local variables

movl    $1, -12(%ebp)        ;val=1

movl    $1, -8(%ebp)        ;nval=1

movl    $1, -16(%ebp)        ;init-expr

jmp     .L16                    ;goto L

.L17:

movl    -8(%ebp), %eax    ;body-statement starts

addl    -12(%ebp), %eax

movl    %eax, -4(%ebp)

movl    -8(%ebp), %eax

movl    %eax, -12(%ebp)

movl    -4(%ebp), %eax

movl    %eax, -8(%ebp)    ;body-statement ends

addl    $1, -16(%ebp)        ;update-expr

.L16:

movl    -16(%ebp), %eax    ;if(i

cmpl    8(%ebp), %eax

jl      .L17

movl    -12(%ebp), %eax    ;reture val

5、switch语句

switch语句提供了根据一个整型索引值进行多重分支的能力。它不但提供了c代码的可读性,而且使用一种称为跳转表的数据结构使得实现更加高效。下面通过例子说明:

/* $begin switch-c */

int switch_eg(int x)

{

int result = x;

switch (x) {

case 100:

result *= 13;

break;

case 102:

result += 10;

/* Fall through */

case 103:

result += 11;

break;

case 104:

case 106:

result *= result;

break;

default:

result = 0;

}

return result;

}

/* $end switch-c */

这个程序不用说,谁都看的懂,下面主要看它所对应的汇编代码:

movl    8(%ebp), %eax                ;x->eax

leal    -100(%eax), %edx            ;x-100->edx

cmpl    $6, %edx                    ;if(x-100>6) goto .L2(default case)

ja      .L2

jmp     *.L7(,%edx,4)                ;redirect jump to .L7+4*edx(goto .L7[edx])

.section        .rodata

.align 4

.align 4

.L7:

.long   .L3                            ;case 100

.long   .L2                            ;default case

.long   .L4                            ;case 102

.long   .L5                            ;case 103

.long   .L6                            ;case 104

.long   .L2                            ;default case

.long   .L6                            ;case 106

.text

.p2align 4,,7

.L2:                                                ;default case

popl    %ebp                            ;result = 0;

xorl    %eax, %eax

ret

.L3:                                                ;case 100

popl    %ebp                            ;result *= 1300 => result = 1300

movl    $1300, %eax

.p2align 4,,6

ret

.L6:                                                ;case 104,106

imull   %eax, %eax                    ;result = result^2

popl    %ebp

.p2align 4,,4

ret

.L5:                                                ;case 103

popl    %ebp                            ;result += 11

movl    $114, %eax

.p2align 4,,4

ret

.L4:                                                ;case 102

popl    %ebp                            ;result += 10

movl    $123, %eax                    ;result += 11

.p2align 4,,4

ret

其中.L7执行的内存空间内存放的就是跳转表,它是一个数组,表项i(.L2--.L6)是一个代码段的地址,这个代码实现的是当开关索引值等于i时程序应该采取的动作。程序代码用开关索引值来执行一个跳转表内的数组引用,确定跳转指令的目标。和使用很长的if-else语句相比,使用跳转表的优点是执行开关语句的时间与开关情况的数量无关。GCC根据开关情况的数量和开关情况值的稀疏程度来翻译开关语句。当开关情况数量比较多,并且值的范围跨度比较小时,就会使用跳转表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值