C程序的机器级表示-4

 
/*********************************************/
       TEXT:     C程序的机器级表示
       AUTHOR:       arden chao
       DATE:     2006-10-17
       EMAIL: arden1019@gmail.com
       VERSION:1.0.0
/*********************************************/
 
/
//2006-10-25 陷入寻址模式
//
 
计算机的寻址模式很复杂 ( 我觉得 ) 。我也陷入其中了,今天不写了。
 
/
//2006-11-06 过程控制
//
 
找不到北了,不知道下面怎么继续。今天来熟悉一下最基本的过程控制吧。
  
int fun_int(int x,int y)
{
    if(x>y)
       x=x-y;
    else
       x=y-x;                      

}

 

// command : gcc -S asm03.c
 
       .file "asm03.c"
       .text
.globl _fun_int
       .def _fun_int; .scl 2;    .type       32;   .endef
_fun_int:
       pushl       %ebp
       movl       %esp, %ebp
       movl       8(%ebp), %eax
       cmpl       12(%ebp), %eax
       jle    L2
       movl       12(%ebp), %eax
       subl %eax, 8(%ebp)
       jmp L3
L2:
       movl       8(%ebp), %eax
       movl       12(%ebp), %edx
       subl %eax, %edx
       movl       %edx, %eax
       movl       %eax, 8(%ebp)
L3:
       popl %ebp
       ret
 
 
       cmpl       12(%ebp), %eax           ;这条语句对x和y进行比较
       jle    L2                 ;如果y<x就跳到L2去
正是上面两句完成了if的功能,说起来,这种程序流程的跳转,我们分成两种,一种叫做无条件的条转,一种叫做条件跳转。带if的是条件跳转,goto是无条件的。
 
可以看看下面的代码了解其中差别:
// filename:asm04.c
/*if and goto*/
 
int fun_goto(int a)
{
    if ( a > 1 )
    {
         a++;
         goto end;
    }
    a--;
end:    
    return a;   
}
 
// command : gcc -S asm04.c
 
       .file "asm04.c"
       .text
.globl _fun_goto
       .def _fun_goto;      .scl 2;    .type       32;   .endef
_fun_goto:
       pushl       %ebp
       movl       %esp, %ebp
       cmpl       $1, 8(%ebp)
       jle    L2
       incl 8(%ebp)
       jmp L3
L2:
       decl 8(%ebp)
L3:
       movl       8(%ebp), %eax
       popl %ebp
       ret
 
其实,回顾一下我们上面的两个程序来看,if可以按照下面的描述来表示:(自CSAPP)
if(test-expr)
 then-statement
else
 else-statement
 
==>
 
 t=test-expr;
 if(t)
    goto true;
 else-statement
    goto done;
true:
 then-statement
done:
 
下面是循环:
其实,循环基本上就是if语句加上一个goto。这个不用细说了吧。我们专门对for做一些认识。
for(init-expr;test-expr;update-expr)
body-statement;
 
可以用下面的while来表示:
init-expr;
while(test-expr)
{
body-statement;
update-expr;
}
 
再展开到goto:
init-expr;
t=test-expr;
if(!t)
 goto done;
loop:
 body-statement;
 update-expr;
 t=test-expr;
 if(t)
    goto loop;
done:
 
顺便我们来看看一种提高for循环效率的方法.
看下面代码:
 
// filename:asm05.c
/*two for function*/
void fun_for1(char *s)
{
    int i;
    for(i=0;i<strlen(s);i++)
    {
    s[i]=0;                   
    }   
}
 
void fun_for2(char *s)
{
     int i,j;
     j=strlen(s);
     for(i=0;i<j;i++)
     {
     s[i]=0;               
     }    
}
 
// command : gcc -S asm05.c
 
       .file "asm05.c"
       .text
.globl _fun_for1
       .def _fun_for1;      .scl 2;    .type       32;   .endef
_fun_for1:
       pushl       %ebp
       movl       %esp, %ebp
       subl $8, %esp
       movl       $0, -4(%ebp)
L2:
       movl       8(%ebp), %eax
       movl       %eax, (%esp)
       call _strlen
       cmpl       %eax, -4(%ebp)
       jae   L1
       movl       8(%ebp), %eax
       addl -4(%ebp), %eax
       movb      $0, (%eax)
       leal   -4(%ebp), %eax
       incl (%eax)
       jmp L2
L1:
       leave
       ret
.globl _fun_for2
       .def _fun_for2;      .scl 2;    .type       32;   .endef
_fun_for2:
       pushl       %ebp
       movl       %esp, %ebp
       subl $24, %esp
       movl       8(%ebp), %eax
       movl       %eax, (%esp)
       call _strlen
       movl       %eax, -8(%ebp)
       movl       $0, -4(%ebp)
L6:
       movl       -4(%ebp), %eax
       cmpl       -8(%ebp), %eax
       jge   L5
       movl       8(%ebp), %eax
       addl -4(%ebp), %eax
       movb      $0, (%eax)
       leal   -4(%ebp), %eax
       incl (%eax)
       jmp L6
L5:
       leave
       ret
       .def _strlen;    .scl 3;    .type       32;   .endef
 
我们经常会在代码中使用for(i=0;i<strlen(s);i++)这样的循环来遍历一个字符串。可是,对于某些情况下,strlen的调用会成为我们程序运行的瓶颈。因为,标准库中对于strlen的实现,其实也是遍历了一遍字符串。只调用一次strlen的代码将运行的更快...(大家可以给上面函数传入一个65535长的字符串并打印时间来看看结果)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值