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