diff --git a/CMakeLists.txt b/CMakeLists.txt
index 128ade2..f5a0897 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -130,7 +130,10 @@ set(SOURCES
   src/libc/stdlib/strtoul.c
   src/libc/stdlib/strtoull.c
   # string
+  src/libc/string/memchr.c
+  src/libc/string/memcmp.c
   src/libc/string/memcpy.c
+  src/libc/string/memmove.c
   src/libc/string/memset.c
   src/libc/string/strcat.c
   src/libc/string/strchr.c
diff --git a/src/libc/string/memchr.c b/src/libc/string/memchr.c
new file mode 100644
index 0000000..00021c6
--- /dev/null
+++ b/src/libc/string/memchr.c
@@ -0,0 +1,16 @@
+#include <string.h>
+
+#ifndef __SUPPORT_ARCH_SH
+
+void *memchr(void const *_s, int c, size_t n)
+{
+	char const *s = _s;
+
+	for(size_t i = 0; i < n; i++) {
+		if(s[i] == c) return (char *)&s[i];
+	}
+
+	return NULL;
+}
+
+#endif /*__SUPPORT_ARCH_SH*/
diff --git a/src/libc/string/memcmp.c b/src/libc/string/memcmp.c
new file mode 100644
index 0000000..976194c
--- /dev/null
+++ b/src/libc/string/memcmp.c
@@ -0,0 +1,18 @@
+#include <string.h>
+
+#ifndef __SUPPORT_ARCH_SH
+
+int memcmp(void const *_s1, void const *_s2, size_t n)
+{
+	char const *s1 = _s1;
+	char const *s2 = _s2;
+
+	for(size_t i = 0; i < n; i++) {
+		int d = s1[i] - s2[i];
+		if(d != 0) return d;
+	}
+
+	return 0;
+}
+
+#endif /*__SUPPORT_ARCH_SH*/
diff --git a/src/libc/string/memmove.c b/src/libc/string/memmove.c
new file mode 100644
index 0000000..3eb0ddb
--- /dev/null
+++ b/src/libc/string/memmove.c
@@ -0,0 +1,22 @@
+#include <string.h>
+
+#ifndef __SUPPORT_ARCH_SH
+
+void *memmove(void *_dest, void const *_src, size_t n)
+{
+	char *dest = _dest;
+	char const *src = _src;
+
+	if(dest <= src) {
+		for(size_t i = 0; i < n; i++)
+			dest[i] = src[i];
+	}
+	else {
+		while(n-- > 0)
+			dest[n] = src[n];
+	}
+
+	return dest;
+}
+
+#endif /*__SUPPORT_ARCH_SH*/