diff --git a/.gitignore b/.gitignore index 8831380..4b37343 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .objs test libasm.a +libasm_bonus.a diff --git a/Makefile b/Makefile index e7635ef..031261c 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,33 @@ NAME ?= libasm.a SRCS_DIR = srcs +SRCS_BONUS_DIR = srcs/bonus OBJS_DIR = .objs -SRCS_NAMES = ft_strlen.s\ - ft_strcpy.s\ - ft_strcmp.s\ - ft_write.s\ - ft_read.s\ - ft_strdup.s +SRCS_NAMES = ft_strlen.s\ + ft_strcpy.s\ + ft_strcmp.s\ + ft_write.s\ + ft_read.s\ + ft_strdup.s + +SRCS_BONUS_NAMES = ft_atoi_base.s SRCS = $(addprefix $(SRCS_DIR)/, $(SRCS_NAMES)) +SRCS_BONUS = $(addprefix $(SRCS_BONUS_DIR)/, $(SRCS_NAMES)) OBJS = $(addprefix $(OBJS_DIR)/, $(SRCS_NAMES:.s=.o)) +OBJS_BONUS = $(addprefix $(OBJS_DIR)/, $(SRCS_BONUS_NAMES:.s=.o)) FLAGS = -felf64 all: $(NAME) + +libasm_bonus.a : $(OBJS_DIR) $(OBJS) $(OBJS_BONUS) + ar rcs libasm_bonus.a $(OBJS) $(OBJS_BONUS) -test: test.c $(NAME) - clang -z noexecstack test.c -L. -lasm -o test -g +test: test.c libasm_bonus.a + clang -z noexecstack test.c -L. -lasm_bonus -o test -g $(NAME): $(OBJS_DIR) $(OBJS) ar rcs $@ $(OBJS) @@ -30,6 +38,9 @@ $(OBJS_DIR): $(OBJS_DIR)/%.o: $(SRCS_DIR)/%.s nasm $(FLAGS) -o $@ $< +$(OBJS_DIR)/%.o: $(SRCS_BONUS_DIR)/%.s + nasm $(FLAGS) -o $@ $< + clean: rm -rf $(OBJS_DIR) diff --git a/README.md b/README.md index 4817d3f..35a5565 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ While doing this project, since I had never programmed in x86_64 assembly before I mostly had trouble with remembering the order of the functions parameters in the registers, I kept going back to [this stackoverflow thread](https://stackoverflow.com/questions/13901261/calling-assembly-function-from-c) provided the order I needed. And in this thread I found information about the System V calling convention. +The order I needed was : rdi, rsi, rdx, rcx, r8, r9 During this project, I also needed to make system calls. To their parameters and numbers, I used [this page](https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/) which has a table of all the system calls. diff --git a/srcs/bonus/ft_atoi_base.s b/srcs/bonus/ft_atoi_base.s new file mode 100644 index 0000000..ef71c63 --- /dev/null +++ b/srcs/bonus/ft_atoi_base.s @@ -0,0 +1,63 @@ +; atoi base +; prototype : int ft_atoi_base(char *str, char *base) + +;global ft_atoi_base +global get_char_index +global check_base + +section .data +invalid_chars: db "+- ", 0x0c, 0x0a, 0x0d, 0x09, 0x0b, 0 + +section .text + +; checks if a char is in the invalid_chars +get_char_index: + xor rax, rax + push rsi + +get_char_index_loop: + cmp dil, [rsi] ;is char invalid + je get_char_index_found + + mov al, [rsi] ; is end of string + test al, al + lea rsi, [rsi + 1] + jne get_char_index_loop + + xor rax, -1 ;not found and at the end + pop rsi + ret + +get_char_index_found: + pop rax ;return index of the found char + sub rsi, rax + mov rax, rsi + ret + +;function that checks if the base is valid +;a valid base does not have any of these char : "+-" or any space defined by isspace(3) and does not have any duplicate char +; returns 0 if base is not valid +check_base: + xor rax, rax + +chk_bs_char: + mov al, [rdi] ; if rdi is \0, return 0 + test al, al + je base_ok + + push rdi ; if current char is in invalid_chars + mov dil, [rdi]; + lea rsi, [rel invalid_chars] + call get_char_index + pop rdi + + cmp rax, -1 ; if not -1, error + lea rdi, [rdi + 1] + je chk_bs_char + + xor rax, rax; return 0 + ret + +base_ok: + mov rax,1 + ret diff --git a/test.c b/test.c index 2f927f3..012c645 100644 --- a/test.c +++ b/test.c @@ -6,7 +6,7 @@ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/29 19:53:58 by tomoron #+# #+# */ -/* Updated: 2025/03/30 15:55:13 by tomoron ### ########.fr */ +/* Updated: 2025/03/31 16:42:55 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ @@ -180,6 +180,21 @@ int test_strdup(void) return(nb_tests == passed); } +size_t check_base(char *base); +int tmp(void) +{ + int nb_tests; + int passed; + + nb_tests = 4; + passed = 0; + + TEST("a", check_base("a") == 1); + TEST("a", check_base("abcdef") == 1); + + return(nb_tests == passed); +} + int main(void) { FNC_TEST("ft_strlen", test_strlen()); @@ -193,4 +208,6 @@ int main(void) FNC_TEST("ft_read", test_read()); printf("\n\n"); FNC_TEST("ft_strdup", test_strdup()); + printf("\n\n"); + FNC_TEST("tmp", tmp()); }