Răsfoiți Sursa

C语言自行实现_strlen_strcpy_strcat和RV汇编代码学习

蘭雅sRGB 4 luni în urmă
părinte
comite
6a61c41f84
3 a modificat fișierele cu 211 adăugiri și 0 ștergeri
  1. 90 0
      libc/libc.c
  2. 121 0
      libc/libc.s
  3. 0 0
      libc/memchr_strlen_diy.c

+ 90 - 0
libc/libc.c

@@ -0,0 +1,90 @@
+#include <stdio.h>
+
+/**
+ * 自行实现strlen函数
+ * @param s 字符串指针
+ * @return 字符串的长度
+ */
+size_t strlen_diy(const char *s) {
+  const char *a = s;
+  while (*s++)
+    ;
+  return s - a - 1;
+}
+
+/**
+ * 自行实现memchr函数
+ * @param src 源数据指针
+ * @param c 要查找的字符
+ * @param n 检查的字符数
+ * @return 找到字符的指针,或NULL
+ */
+void *memchr_diy(const void *src, int c, size_t n) {
+  const unsigned char *s = src;
+  c = (unsigned char)c;
+
+  for (; n && *s != c; s++, n--)
+    ;
+
+  return n ? (void *)s : 0;
+}
+
+/**
+ * 自行实现strnlen函数
+ * @param s 字符串指针
+ * @param n 最大检查长度
+ * @return 字符串的实际长度,或n
+ */
+size_t strnlen_diy(const char *s, size_t n) {
+  const char *p = memchr_diy(s, 0, n);
+  return p ? p - s : n;
+}
+
+/**
+ * 自行实现strcpy函数
+ * @param d 目标字符串指针
+ * @param s 源字符串指针
+ * @return 目标字符串指针
+ */
+char *strcpy_diy(char *d, const char *s) {
+  char *p = d;
+  // for (; (*d = *s); s++, d++) ;
+  while ((*d++ = *s++))
+    ;
+  return p;
+}
+
+/**
+ * 自行实现strcat函数
+ * @param d 目标字符串指针
+ * @param s 源字符串指针
+ * @return 目标字符串指针
+ */
+char *strcat_diy(char *d, const char *s) {
+  strcpy_diy(d + strlen_diy(d), s);
+  return d;
+}
+
+int main() {
+  char str[] = "Hello World -> (strlen_diy memchr_diy strcpy_diy strcat_diy)";
+  // 使用memchr_diy查找字符'('的位置
+  puts(memchr_diy(str, '(', strlen_diy(str)));
+
+  // 使用strlen_diy计算字符串长度
+  int len = strlen_diy(str);
+  printf("len: %d\n", len);
+
+  // 使用strnlen_diy计算字符串长度,限制最大检查长度为100
+  len = strnlen_diy(str, 100);
+  printf("len: %d\n", len); 
+
+  // 使用strcpy_diy复制字符串
+  char *s = strcpy_diy(str, "Hello C/C++ LIBC:");
+  printf("%s\n", s);
+
+  // 使用strcat_diy追加字符串
+  s = strcat_diy(str, "-> strcat_diy");
+  printf("%s\n", s);
+  return 0;
+}
+

+ 121 - 0
libc/libc.s

@@ -0,0 +1,121 @@
+strlen_diy:
+	mv	a5,a0
+.L2:
+	lbu	a4,0(a5)
+	addi	a5,a5,1
+	bne	a4,zero,.L2
+	sub	a0,a5,a0
+	addi	a0,a0,-1
+	ret
+
+memchr_diy:
+	andi	a1,a1,0xff
+.L5:
+	beq	a2,zero,.L8
+	lbu	a5,0(a0)
+	bne	a5,a1,.L7
+	ret
+.L7:
+	addi	a0,a0,1
+	addi	a2,a2,-1
+	j	.L5
+.L8:
+	li	a0,0
+	ret
+
+strnlen_diy:
+	addi	sp,sp,-32
+	sd	s0,16(sp)
+	mv	a2,a1
+	mv	s0,a1
+	li	a1,0
+	sd	s1,8(sp)
+	sd	ra,24(sp)
+	mv	s1,a0
+	call	memchr_diy
+	beq	a0,zero,.L10
+	sub	s0,a0,s1
+.L10:
+	ld	ra,24(sp)
+	mv	a0,s0
+	ld	s0,16(sp)
+	ld	s1,8(sp)
+	addi	sp,sp,32
+	jr	ra
+
+strcpy_diy:
+	mv	a5,a0
+.L16:
+	lbu	a4,0(a1)
+	addi	a1,a1,1
+	addi	a5,a5,1
+	sb	a4,-1(a5)
+	bne	a4,zero,.L16
+	ret
+
+strcat_diy:
+	addi	sp,sp,-32
+	sd	ra,24(sp)
+	sd	s0,16(sp)
+	sd	a1,8(sp)
+	mv	s0,a0
+	call	strlen_diy
+	ld	a1,8(sp)
+	add	a0,s0,a0
+	call	strcpy_diy
+	ld	ra,24(sp)
+	mv	a0,s0
+	ld	s0,16(sp)
+	addi	sp,sp,32
+	jr	ra
+
+.LC1:
+	.string	"len: %d\n"
+.LC2:
+	.string	"Hello C/C++ LIBC:"
+.LC3:
+	.string	"-> strcat_diy"
+.LC0:
+	.string	"Hello World -> (strlen_diy memchr_diy strcpy_diy strcat_diy)"
+
+	.type	main, @function
+main:
+	addi	sp,sp,-80
+	sd	s0,64(sp)
+	mv	s0,sp
+	li	a2,61
+	lla	a1,.LC0
+	mv	a0,s0
+	sd	ra,72(sp)
+	call	memcpy@plt
+	mv	a0,s0
+	call	strlen_diy
+	mv	a2,a0
+	li	a1,40
+	mv	a0,s0
+	call	memchr_diy
+	call	puts@plt
+	mv	a0,s0
+	call	strlen_diy
+	sext.w	a1,a0
+	lla	a0,.LC1
+	call	printf@plt
+	li	a1,100
+	mv	a0,s0
+	call	strnlen_diy
+	sext.w	a1,a0
+	lla	a0,.LC1
+	call	printf@plt
+	lla	a1,.LC2
+	mv	a0,s0
+	call	strcpy_diy
+	call	puts@plt
+	lla	a1,.LC3
+	mv	a0,s0
+	call	strcat_diy
+	call	puts@plt
+	ld	ra,72(sp)
+	ld	s0,64(sp)
+	li	a0,0
+	addi	sp,sp,80
+	jr	ra

+ 0 - 0
memchr_strlen_diy.c → libc/memchr_strlen_diy.c