028 函数的返回值

/*******************028 函数的返回值*************************
 * 函数find_substr()返回串内一字符串的开始位置或未发现匹配字符
 * 串时返回-1. 
 * C语言精彩编程百例 第28*/

#include<stdio.h>

int find_substr(char* s1,char* s2);

int main()
{
    if(find_substr("C is fun","is")!=-1)
        printf("Substring is founs.\n");
    return 0;
}

int find_substr(char* s1, char* s2)
{
    register int t;
    char *p, *p2;

    for(t=0;s1[t];t++)
    {
        p=&s1[t];
        p2=s2;

        while(*p2 && *p2==*p)
        {
            p++;
            p2++;
        }
        if(! *p2)
            return t;

    }
    return -1;

}
    .file   "028.c"
    .def    ___main;    .scl    2;  .type   32; .endef
    .text
LC0:
    .ascii "is\0"
LC1:
    .ascii "C is fun\0"
LC2:
    .ascii "Substring is founs.\12\0"
    .align 2
.globl _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    andl    $-16, %esp
    movl    $0, %eax
    movl    %eax, -4(%ebp)
    movl    -4(%ebp), %eax
    call    __alloca
    call    ___main
    subl    $8, %esp
    pushl   $LC0		# 立即数$LC0 是"is\0"的地址,而不是"is\0"的值 
    pushl   $LC1       # "C is fun\0"的地址
    call    _find_substr
    addl    $16, %esp  # 平衡堆栈
    cmpl    $-1, %eax  # 
    je  L4      #if(find_substr("C is fun","is")!=-1)
    subl    $12, %esp
    pushl   $LC2       #"Substring is founs.\12\0"
    call    _printf
    addl    $16, %esp
L4:
    movl    $0, %eax   # retrun 0
    leave
    ret


    .align 2
.globl _find_substr
    .def    _find_substr;   .scl    2;  .type   32; .endef
_find_substr:
    pushl   %ebp            # 调整基址
    movl    %esp, %ebp      # 
    subl    $16, %esp      # 设置栈空间
    movl    $0, -16(%ebp)
L6:
    movl    8(%ebp), %eax       # eax= s1 
    movl    -16(%ebp), %edx     # edx =t
    cmpb    $0, (%edx,%eax)        # if *(s1+t) !=0
    jne L9
    jmp L7
L9:
    movl    -16(%ebp), %eax     # eax=t
    addl    8(%ebp), %eax       # eax=s1+t
    movl    %eax, -4(%ebp)      # p=&s1[t]
    movl    12(%ebp), %eax      # eax=s2
    movl    %eax, -8(%ebp)      # p2=s2
L10:
    movl    -8(%ebp), %eax      # eax=p2
    cmpb    $0, (%eax)     # if *p2
    je  L11
    movl    -8(%ebp), %eax      # eax=p2
    movl    -4(%ebp), %edx      # edx=p
    movb    (%eax), %al     # al=*p2
    cmpb    (%edx), %al     # if *p == *p2
    je  L12
    jmp L11
L12:
    leal    -4(%ebp), %eax      # eax=&p
    incl    (%eax)          # p++
    leal    -8(%ebp), %eax      # eax=&p2
    incl    (%eax)          # p2++
    jmp L10
L11:
    movl    -8(%ebp), %eax      # eax= p2
    cmpb    $0, (%eax)     # if *p2
    jne L8
    movl    -16(%ebp), %eax     # eax =t
    movl    %eax, -12(%ebp)     # 这里没有直接return,而是用一个隐藏的变量,用于保存return的值,然后跳转 
    jmp L5
L8:
    incl    -16(%ebp)       # t++  这里就不是 leal -16(%ebp),eax incl (%eax) 这种最常见的样式
    jmp L6
L7:
    movl    $-1, -12(%ebp)
L5:
    movl    -12(%ebp), %eax
    leave
    ret
    .def    _printf;    .scl    2;  .type   32; .endef
    .def    _find_substr;   .scl    2;  .type   32; .endef

几个有意思的地方:

  1. 尽管1个函数内包含了2个return语句, 但在编译结果中, 并没有直接将2个retrun 都编译为ret, 而是优化为一个return。为此编译器添加了一个隐含的变量。 具体编译器是怎么做到的,将来学编译原理时再研究。
  2. 在 find_substr(“C is fun”,”is”) 中,传递的参数”C is fun” 和”is” 的数据类型是char* – 指向char的指针, 就是传递的是地址常量而不是字符串本身。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值