diff --git a/.objs/ft_read.o b/.objs/ft_read.o new file mode 100644 index 0000000..eeb6146 Binary files /dev/null and b/.objs/ft_read.o differ diff --git a/.objs/ft_strcmp.o b/.objs/ft_strcmp.o new file mode 100644 index 0000000..960ea57 Binary files /dev/null and b/.objs/ft_strcmp.o differ diff --git a/.objs/ft_strcpy.o b/.objs/ft_strcpy.o new file mode 100644 index 0000000..68931a7 Binary files /dev/null and b/.objs/ft_strcpy.o differ diff --git a/.objs/ft_strdup.o b/.objs/ft_strdup.o new file mode 100644 index 0000000..3152a8f Binary files /dev/null and b/.objs/ft_strdup.o differ diff --git a/.objs/ft_strlen.o b/.objs/ft_strlen.o new file mode 100644 index 0000000..2785c58 Binary files /dev/null and b/.objs/ft_strlen.o differ diff --git a/.objs/ft_write.o b/.objs/ft_write.o new file mode 100644 index 0000000..82a206b Binary files /dev/null and b/.objs/ft_write.o differ diff --git a/Makefile b/Makefile index c23cb88..e7635ef 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ FLAGS = -felf64 all: $(NAME) test: test.c $(NAME) - clang -z noexecstack test.c $(NAME) -o test + clang -z noexecstack test.c -L. -lasm -o test -g $(NAME): $(OBJS_DIR) $(OBJS) ar rcs $@ $(OBJS) diff --git a/libasm.a b/libasm.a new file mode 100644 index 0000000..530d488 Binary files /dev/null and b/libasm.a differ diff --git a/patate.c b/patate.c new file mode 100644 index 0000000..d0d0c2d --- /dev/null +++ b/patate.c @@ -0,0 +1,7 @@ +#include +#include + +int main(void) +{ + printf("%d\n", strcmp("coucou", "c")); +} diff --git a/srcs/ft_read.s b/srcs/ft_read.s index e69de29..96197db 100644 --- a/srcs/ft_read.s +++ b/srcs/ft_read.s @@ -0,0 +1,19 @@ +global ft_read +extern __errno_location +section .text + +ft_read: + mov rax, 0 ;syscall number for read, args are already set at the right place + syscall + + cmp rax, 0 ; if return is < 0, it's an error in negative + jg success + + neg rax ; inv errno, and set errno + mov edi, eax + call __errno_location wrt ..plt + mov [rax], edi + mov rax, -1 + +success: + ret diff --git a/srcs/ft_strcmp.s b/srcs/ft_strcmp.s index e69de29..f33f554 100644 --- a/srcs/ft_strcmp.s +++ b/srcs/ft_strcmp.s @@ -0,0 +1,48 @@ +section .text + global ft_strcmp + +ft_strcmp: + xor rax, rax + + test rdi, rdi ; test if args are false + je err + test rsi, rsi + je err +loop_start: + mov al, [rdi] + cmp al, [rsi] + jne compare + + test al, al ; test if rdi is \0 + je compare + + mov al, [rsi] ; test if rsi is \0 + test al, al + je compare + + lea rsi, [rsi + 1] + lea rdi, [rdi + 1] + jmp loop_start + + +compare: + mov al, [rdi] + cmp al, [rsi] + jl lower + jg greater + mov eax, 0 + jmp end + +lower: + mov eax, -1 + jmp end + +greater: + mov eax, 1 + jmp end + +err: + mov eax, 0 + +end: + ret diff --git a/srcs/ft_strcpy.s b/srcs/ft_strcpy.s index e69de29..5bfc62a 100644 --- a/srcs/ft_strcpy.s +++ b/srcs/ft_strcpy.s @@ -0,0 +1,29 @@ +section .text + global ft_strcpy + +ft_strcpy: + test rdi, rdi + je err + test rsi, rsi + je err + push rdi + jmp loop_start +condition_check: + mov al, [rdi] + test al, al + je end + +loop_start: + mov rax, [rsi] + mov [rdi], rax + lea rdi, [rdi + 1] + lea rsi, [rsi + 1] + jmp condition_check + +end: + pop rax + ret + +err: + xor rax, rax + ret diff --git a/srcs/ft_strdup.s b/srcs/ft_strdup.s index e69de29..613bf50 100644 --- a/srcs/ft_strdup.s +++ b/srcs/ft_strdup.s @@ -0,0 +1,31 @@ +extern malloc +global ft_strdup +extern ft_strcpy +extern ft_strlen +extern __errno_location +section .text + +ft_strdup: + test rdi, rdi ; test if arg is NULL + je err + + push rdi ;push to use it for the strcpy + call ft_strlen + mov rdi, rax + + call malloc wrt ..plt + test rax, rax + je malloc_failed + mov rdi, rax + pop rsi + call ft_strcpy + ret + +malloc_failed: + call __errno_location wrt ..plt + mov dword [rax], 12 + pop rax + +err: + xor rax, rax + ret diff --git a/srcs/ft_write.s b/srcs/ft_write.s index e69de29..355fab5 100644 --- a/srcs/ft_write.s +++ b/srcs/ft_write.s @@ -0,0 +1,20 @@ +global ft_write +extern __errno_location +section .text + +ft_write: + mov rax, 1 ;syscall number for write, args are already set at the right place + syscall + + cmp rax, 0 ; if return is < 0, it's an error in negative + jg success + + neg rax ; inv errno, and set errno + mov edi, eax + call __errno_location wrt ..plt + mov [rax], edi + mov rax, -1 + + +success: + ret diff --git a/test b/test new file mode 100755 index 0000000..0f950da Binary files /dev/null and b/test differ diff --git a/test.c b/test.c index 5994364..21751e8 100644 --- a/test.c +++ b/test.c @@ -1,27 +1,49 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* test.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: tomoron +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/03/29 19:53:58 by tomoron #+# #+# */ +/* Updated: 2025/03/29 19:54:24 by tomoron ### ########.fr */ +/* */ +/* ************************************************************************** */ + #include +#include #include +#include +#include +#include #define OK "\033[32mOK\n\033[0m" #define KO "\033[31mKO\n\033[0m" #define FNC_TEST(title, condition)\ printf(title":\n");\ - if(test_strlen())\ + if(condition)\ printf("RESULT: "OK);\ else\ printf(" RESULT: "KO); #define TEST(title, condition) \ - printf("%s: ", title);\ + write(1, title, strlen(title));\ + write(1, ": ", 2);\ if(condition)\ {\ - printf(OK);\ + write(1, OK, strlen(OK));\ passed++;\ }\ else \ - printf(KO); + write(1, KO, strlen(KO));\ -size_t ft_strlen(char *str); +size_t ft_strlen(char *str); +char *ft_strcpy(char *dest, char *src); +int ft_strcmp(char *dest, char *src); +ssize_t ft_write(int fd, const void *buffer, size_t count); +ssize_t ft_read(int fd, void *buffer, size_t count); +char *ft_strdup(char *src); int test_strlen(void) { @@ -38,8 +60,136 @@ int test_strlen(void) return(nb_tests == passed); } +int test_strcpy(void) +{ + int nb_tests; + int passed; + char buf[256]; + + memset(buf,'a', 255); + buf[255] = 0; + + nb_tests = 5; + passed = 0; + + TEST("copy normal string", strcmp(ft_strcpy(buf, "hello"),"hello") == 0); + TEST("copy empty string", strcmp(ft_strcpy(buf, ""),"") == 0); + TEST("copy to null pointer", ft_strcpy(NULL, "") == 0); + TEST("copy from null pointer", ft_strcpy("", NULL) == 0); + TEST("copy from and to null pointer", ft_strcpy(NULL, NULL) == 0); + + return(nb_tests == passed); +} + +int test_strcmp(void) +{ + int nb_tests; + int passed; + + nb_tests = 5; + passed = 0; + + TEST("equal string", ft_strcmp("coucou", "coucou") == 0); + TEST("second smaller string", ft_strcmp("coucou", "c") == 1); + TEST("first smaller string", ft_strcmp("c", "coucou") == -1); + TEST("first null", ft_strcmp(NULL, "coucou") == 0); + TEST("second null", ft_strcmp("hello", NULL) == 0); + + return(nb_tests == passed); +} + +int test_write(void) +{ + int nb_tests; + int passed; + + nb_tests = 5; + passed = 0; + + TEST("writing hello and test return value", ft_write(1, "hello ", 6) == 6); + errno = 0; + TEST("failed write return value", ft_write(-1, "", 0) == (size_t)-1); + TEST("failed write errno test", errno == 9); + errno = 0; + TEST("call write with null pointer, return value", ft_write(1, NULL, 1) == (size_t)-1); + TEST("call write with null pointer, errno", errno == 14); + + return(nb_tests == passed); +} + +int test_read(void) +{ + int nb_tests; + int passed; + int fd; + char buf[512]; + + nb_tests = 8; + passed = 0; + + printf("creating test file to test the read function\n"); + fd = open("test_file.tmp", O_WRONLY | O_CREAT, 0600); + write(fd, "patate douce", 12); + close(fd); + + fd = open("test_file.tmp", O_RDONLY); + TEST("read 1 char", ft_read(fd, buf, 1) == 1); + TEST("check read char", memcmp(buf, "p", 1) == 0); + TEST("read multiple char", ft_read(fd, buf, 5) == 5); + TEST("compare with expected", memcmp(buf, "atate", 5) == 0); + + errno = 0; + TEST("invalid fd read, return", ft_read(-1, buf, 20) == (size_t)-1); + TEST("invalid fd read, errno", errno == 9); + errno = 0; + TEST("read to null pointer, return", ft_read(fd, NULL, 4) == (size_t)-1) + TEST("read to null pointer, errno", errno == 14) + close(fd); + + return(nb_tests == passed); +} + +int test_strdup(void) +{ + int nb_tests; + int passed; + char *src = "patate douce"; + char *dest; + + nb_tests = 4; + passed = 0; + + dest = ft_strdup(src); + + if(!dest) + { + printf("strdup failed, probably testing errno, returing with result\n"); + return(errno == ENOMEM); + } + + TEST("strdup normal stiring, diff pointer", dest != src); + TEST("strdup normal string , content", !strcmp(dest, src)); + free(dest); + + dest = ft_strdup(""); + TEST("strdup empty string", *dest == 0); + free(dest); + TEST("strdup null pointer", ft_strdup(NULL) == NULL); + + return(nb_tests == passed); +} + int main(void) { FNC_TEST("ft_strlen", test_strlen()); printf("\n\n"); + FNC_TEST("ft_strcpy", test_strcpy()); + printf("\n\n"); + FNC_TEST("ft_strcmp", test_strcmp()); + printf("\n\n"); + FNC_TEST("ft_write", test_write()); + printf("\n\n"); + FNC_TEST("ft_read", test_read()); + printf("\n\n"); + FNC_TEST("ft_strdup", test_strdup()); } diff --git a/test_file.tmp b/test_file.tmp new file mode 100644 index 0000000..5742772 --- /dev/null +++ b/test_file.tmp @@ -0,0 +1 @@ +patate douce \ No newline at end of file