add other basic functions and test with them

This commit is contained in:
2025-03-29 19:54:58 +01:00
parent 76cf33dd1c
commit b6ad45ab6d
17 changed files with 311 additions and 6 deletions

BIN
.objs/ft_read.o Normal file

Binary file not shown.

BIN
.objs/ft_strcmp.o Normal file

Binary file not shown.

BIN
.objs/ft_strcpy.o Normal file

Binary file not shown.

BIN
.objs/ft_strdup.o Normal file

Binary file not shown.

BIN
.objs/ft_strlen.o Normal file

Binary file not shown.

BIN
.objs/ft_write.o Normal file

Binary file not shown.

View File

@ -19,7 +19,7 @@ FLAGS = -felf64
all: $(NAME) all: $(NAME)
test: test.c $(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) $(NAME): $(OBJS_DIR) $(OBJS)
ar rcs $@ $(OBJS) ar rcs $@ $(OBJS)

BIN
libasm.a Normal file

Binary file not shown.

7
patate.c Normal file
View File

@ -0,0 +1,7 @@
#include <string.h>
#include <stdio.h>
int main(void)
{
printf("%d\n", strcmp("coucou", "c"));
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

BIN
test Executable file

Binary file not shown.

160
test.c
View File

@ -1,27 +1,49 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* test.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/29 19:53:58 by tomoron #+# #+# */
/* Updated: 2025/03/29 19:54:24 by tomoron ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define OK "\033[32mOK\n\033[0m" #define OK "\033[32mOK\n\033[0m"
#define KO "\033[31mKO\n\033[0m" #define KO "\033[31mKO\n\033[0m"
#define FNC_TEST(title, condition)\ #define FNC_TEST(title, condition)\
printf(title":\n");\ printf(title":\n");\
if(test_strlen())\ if(condition)\
printf("RESULT: "OK);\ printf("RESULT: "OK);\
else\ else\
printf(" RESULT: "KO); printf(" RESULT: "KO);
#define TEST(title, condition) \ #define TEST(title, condition) \
printf("%s: ", title);\ write(1, title, strlen(title));\
write(1, ": ", 2);\
if(condition)\ if(condition)\
{\ {\
printf(OK);\ write(1, OK, strlen(OK));\
passed++;\ passed++;\
}\ }\
else \ 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) int test_strlen(void)
{ {
@ -38,8 +60,136 @@ int test_strlen(void)
return(nb_tests == passed); 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) int main(void)
{ {
FNC_TEST("ft_strlen", test_strlen()); FNC_TEST("ft_strlen", test_strlen());
printf("\n\n"); 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());
} }

1
test_file.tmp Normal file
View File

@ -0,0 +1 @@
patate douce