diff options
| -rw-r--r-- | LICENSE | 21 | ||||
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | README.md | 18 | ||||
| -rw-r--r-- | ft_list_push_front.s | 27 | ||||
| -rw-r--r-- | ft_list_remove_if.s | 88 | ||||
| -rw-r--r-- | ft_list_size.s | 6 | ||||
| -rw-r--r-- | ft_list_sort.s | 155 | ||||
| -rw-r--r-- | ft_read.s | 30 | ||||
| -rw-r--r-- | ft_write.s | 32 | ||||
| -rw-r--r-- | main.c | 154 |
10 files changed, 420 insertions, 117 deletions
@@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 HappyTramp + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. @@ -6,7 +6,7 @@ # By: cacharle <marvin@42.fr> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2019/11/22 02:56:22 by cacharle #+# #+# # -# Updated: 2019/11/25 04:46:29 by cacharle ### ########.fr # +# Updated: 2020/04/12 19:53:58 by charles ### ########.fr # # # # **************************************************************************** # @@ -26,8 +26,8 @@ endif NAME = libasm.a ASMSRC = ft_strlen.s ft_strcpy.s ft_strcmp.s ft_write.s ft_read.s \ - ft_strdup.s ft_atoi_base.s #ft_list_push_front.s \ - # ft_list_size.s ft_list_sort.s ft_list_remove_if.s + ft_strdup.s ft_atoi_base.s ft_list_push_front.s \ + ft_list_size.s ft_list_sort.s ft_list_remove_if.s ASMOBJ = $(ASMSRC:.s=.o) TESTNAME = runtest diff --git a/README.md b/README.md new file mode 100644 index 0000000..2bd0427 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# libasm + +libasm project of school 42. + +## Test + +Clone the test [repository](https://github.com/HappyTramp/libasm_test) next to this project folder. + +``` +. +|- libasm +|- libasm_test +``` + +``` +cd libasm_test +make runbonus +``` diff --git a/ft_list_push_front.s b/ft_list_push_front.s index 686ee10..320c49c 100644 --- a/ft_list_push_front.s +++ b/ft_list_push_front.s @@ -10,13 +10,28 @@ ; ; ; **************************************************************************** ; -global _ft_list_push_front +extern _malloc + +global ft_list_push_front ; void ft_list_push_front(t_list **begin_list, void *data); -_ft_list_push_front: - cmp rdi, 0 - je FT_LIST_PUSH_FRONT_END - mov [rsi + 8], [rdi] - mov [rdi], rsi +ft_list_push_front: + cmp rdi, 0 + je FT_LIST_PUSH_FRONT_END + + push rdi + push rsi + xor rdi, rdi + mov edi, 16 + call _malloc + pop rsi + pop rdi + cmp rax, 0 + je FT_LIST_PUSH_FRONT_END + + mov qword [rax + 0], rsi + mov r10, [rdi] + mov [rax + 8], r10 + mov [rdi], rax FT_LIST_PUSH_FRONT_END: ret diff --git a/ft_list_remove_if.s b/ft_list_remove_if.s index 9ae6ba5..40e2415 100644 --- a/ft_list_remove_if.s +++ b/ft_list_remove_if.s @@ -10,49 +10,85 @@ ; ; ; **************************************************************************** ; -global _ft_list_remove_if +global ft_list_remove_if + +extern _free + +%define NULL 0x0 + +%macro EXTERN_FUNCTION_SAVE 0 + push rdi + push rsi + push rdx + push rcx +%endmacro + +%macro EXTERN_FUNCTION_SAVE_END 0 + pop rcx + pop rdx + pop rsi + pop rdi +%endmacro ; ft_list_remove_if(t_list **begin_list, void *data_ref, -; int (*cmp)(), void (*free_fct)(void *)) +; int (*cmp)(void *data, void *data_ref), +; void (*free_fct)(void *)) +ft_list_remove_if: + ; t_list *saved_next -_ft_list_remove_if: + ; === prolog === + push rbp + mov rbp, rsp sub rsp, 8 - cmp rdi, 0x0 + ; === base condition === + cmp rdi, NULL je FT_LIST_REMOVE_IF_END - cmp [rdi], 0x0 + cmp qword [rdi], NULL je FT_LIST_REMOVE_IF_END - push rdi - mov rdi, [rdi] + 8 ;&(*begin_list)->val - call rdx - pop rdi - cmp rax, 0x0 + ; === compare (*begin_list)->data and data_ref + EXTERN_FUNCTION_SAVE + mov rdi, [rdi] + mov rdi, [rdi + 0] + call rdx ; cmp((*begin_list)->data, data_ref) + EXTERN_FUNCTION_SAVE_END + cmp rax, 0 je FT_LIST_REMOVE_IF_REMOVE - - mov rdi, [rdi] + 8 - call _ft_list_remove_if - add rsp, 8 - ret - -FT_LIST_REMOVE_IF_REMOVE: - mov [rsp], [rdi] + 8 ; saved_next = (*begin_list)->next - + ; === next element === push rdi - mov rdi, [[rdi]] - call rcx ; free_fct((*begin_list)->data) + mov rdi, [rdi] + lea rdi, [rdi + 8] + call ft_list_remove_if pop rdi + jmp FT_LIST_REMOVE_IF_END - push rdi + ; === remove head and go next === +FT_LIST_REMOVE_IF_REMOVE: + mov rax, [rdi] ; rax = *begin_list + mov rax, [rax + 8] ; rax = rax->next + mov [rbp - 8], rax ; saved_next = (*begin_list)->next + + push rdi ; strange behavior + EXTERN_FUNCTION_SAVE mov rdi, [rdi] - call _free ; free(*begin_list) + mov rdi, [rdi + 0] + call rcx ; free_fct((*begin_list)->data) + EXTERN_FUNCTION_SAVE_END pop rdi - mov [rdi], [rsp] ; *begin_list = saved_next + EXTERN_FUNCTION_SAVE + mov rdi, [rdi] + call _free ; free(*begin_list) + EXTERN_FUNCTION_SAVE_END - call _ft_list_remove_if + mov rax, [rbp - 8] + mov [rdi], rax + call ft_list_remove_if FT_LIST_REMOVE_IF_END: - add rsp, 8 + ; === epilog === + mov rsp, rbp + pop rbp ret diff --git a/ft_list_size.s b/ft_list_size.s index ad89999..5367a17 100644 --- a/ft_list_size.s +++ b/ft_list_size.s @@ -10,10 +10,10 @@ ; ; ; **************************************************************************** ; -global _ft_list_size +global ft_list_size ; int ft_list_size(t_list *begin_list); -_ft_list_size: +ft_list_size: xor eax, eax FT_LIST_SIZE_LOOP: cmp rdi, 0 @@ -21,5 +21,5 @@ FT_LIST_SIZE_LOOP: inc eax mov rdi, [rdi + 8] jmp FT_LIST_SIZE_LOOP -FT_LIST_SIZE_END +FT_LIST_SIZE_END: ret diff --git a/ft_list_sort.s b/ft_list_sort.s index 23924e1..b077b89 100644 --- a/ft_list_sort.s +++ b/ft_list_sort.s @@ -10,108 +10,117 @@ ; ; ; **************************************************************************** ; -global _ft_list_sort - -; void ft_list_sort(t_list **begin_list, int (*cmp)()); -_ft_list_sort: - ; t_list *fast - ; t_list *slow - ; t_list *middle - sub rsp, 24 - - cmp rdi, 0x0 - je FT_LIST_SORT_END - cmp [rdi], 0x0 - je FT_LIST_SORT_END - cmp [[rdi] + 8], 0x0 ; use tmp register - je FT_LIST_SORT_END - - mov [rsp], [[rdi] + 8] - mov [rsp + 8], [rdi] -FT_GET_MIDDLE_LOOP: - mov [rsp], [rsp + 8] - cmp [rsp], 0x0 - je FT_GET_MIDDLE_LOOP_END - mov [rsp], [rsp + 8] - mov [rsp + 8], [[rsp + 8] + 8] ; i want c pointers back plz -FT_GET_MIDDLE_LOOP_END: - mov [rsp + 16], [[rsp + 8] + 8] - mov [[rsp + 8] + 8], 0x0 +global ft_list_sort + +%define NULL 0x0 + +; void ft_list_sort(t_list **begin_list, int (*cmp)(void*, void*)); +ft_list_sort: + ; t_list *slow : rax = *begin_list + ; t_list *fast : rbx = (*begin_list)->next + ; t_list *middle : rsp + 0 + + ; === base condition === + cmp rdi, NULL + je FT_LIST_SORT_END ; if begin_list == NULL return + mov rax, [rdi] + cmp rax, NULL + je FT_LIST_SORT_END ; if *begin_list == NULL return + mov rbx, [rax + 8] + cmp rbx, NULL + je FT_LIST_SORT_END ; if (*begin_list)->next == NULL return + + ; === find list middle loop === +FT_LIST_SORT_MIDDLE_LOOP: ; do { + mov rbx, [rbx + 8] ; fast = fast->next + cmp rbx, NULL + je FT_LIST_SORT_MIDDLE_LOOP_END ; if fast == NULL break + mov rbx, [rbx + 8] ; fast = fast->next + mov rax, [rax + 8] ; slow = slow->next + cmp rbx, NULL + jne FT_LIST_SORT_MIDDLE_LOOP ; } while (fast != NULL) +FT_LIST_SORT_MIDDLE_LOOP_END: + + ; create a stack frame for local variable to store middle address + push rbp + mov rbp, rsp + sub rsp, 8 - push rdi - call _ft_list_sort - pop rdi + ; store middle in [rbp - 8] + mov rcx, [rax + 8] + mov [rbp - 8], rcx + mov qword [rax + 8], NULL ; slow->next = NULL + ; === sorting both child list === push rdi - mov rdi, [rsp + 16] - call _ft_list_sort + push rsi + call ft_list_sort ; ft_list_sort(begin_list, cmp) + lea rdi, [rbp - 8] + call ft_list_sort ; ft_list_sort(&middle, cmp) + pop rsi pop rdi + ; === merging sorted child === push rdi push rsi - mov rdx, rsi - mov rdi, [rdi] - mov rsi, [rsp + 16] - call _merge_sorted_list + mov rdi, [rdi] ; arg_1 = *begin_list + mov rdx, rsi ; arg_3 = cmp + mov rsi, [rbp - 8] ; arg_2 = middle + call _st_merge_sorted_list pop rsi pop rdi + mov [rdi], rax ; *begin_list = st_merge_sorted_list(...); - mov [rdi], rax - - add rsp, 24 + ; restoring stack frame + mov rsp, rbp + pop rbp FT_LIST_SORT_END: ret - -; t_list *merge_sorted_list(t_list* l1, t_list* l2, int (*cmp)()) -_merge_sorted_list: - sub rsp, 8 - - cmp rdi, 0x0 - je MERGE_SORTED_LIST_RETURN_L2 - cmp rsi, 0x0 - je MERGE_SORTED_LIST_RETURN_L1 +; t_list *st_merge_sorted_list(t_list* l1, t_list* l2, int (*cmp)(void*, void*)) +_st_merge_sorted_list: + cmp rdi, NULL + je MERGE_SORTED_LIST_RETURN_L2 ; if l1 == NULL return l2 + cmp rsi, NULL + je MERGE_SORTED_LIST_RETURN_L1 ; if l2 == NULL return l1 push rdi push rsi - mov rdi, [rdi] - mov rsi, [rsi] - call rdx ; cmp + push rdx + mov rdi, [rdi + 0] ; l1->data + mov rsi, [rsi + 0] ; l2->data + xor rax, rax + call rdx ; cmp + pop rdx pop rsi pop rdi - cmp rax, 0x0 - jl L1_LT_L2 + cmp eax, 0 + jl MERGE_SORTED_LIST_L1_LT_L2 -; L1_GE_L2 - mov rsp, rsi + ; if l1 >= l2 + push rsi ; save l2 + mov rsi, [rsi + 8] ; l2 = l2->next + call _st_merge_sorted_list ; merge_sorted_list(l1, l2->next, cmp) + pop rsi ; restore rsi + mov [rsi + 8], rax + mov rax, rsi + jmp MERGE_SORTED_LIST_END + ; else +MERGE_SORTED_LIST_L1_LT_L2: push rdi - push rsi mov rdi, [rdi + 8] - call _merge_sorted_list - pop rsi + call _st_merge_sorted_list ; merge_sort_list(l1->next, l2, cmp) pop rdi - mov [rsp + 8], rax + mov [rdi + 8], rax + mov rax, rdi jmp MERGE_SORTED_LIST_END -L1_LT_L2: - mov rsp, rdi - push rdi - push rsi - mov rsi, [rsi + 8] - call _merge_sorted_list - pop rsi - pop rdi - mov [rsp + 8], rax - -MERGE_SORTED_LIST_END: - mov rax, [rsp] - add rsp, 8 - ret MERGE_SORTED_LIST_RETURN_L1: mov rax, rdi ret MERGE_SORTED_LIST_RETURN_L2: mov rax, rsi +MERGE_SORTED_LIST_END: ret @@ -12,8 +12,36 @@ global ft_read +%define F_GETFD 1 +%define SYSCALL_READ 0x2000003 +%define SYSCALL_FCNTL 0x200005c + ; int ft_read(int, void*, size_t); ft_read: - mov rax, 0x2000003 + cmp rdx, 0 + je FT_READ_NO_SIZE + cmp rdi, 0 + jl FT_READ_ERROR + cmp rsi, 0 + je FT_READ_ERROR + + push rdx + push rsi + xor rsi, rsi + mov esi, F_GETFD + mov rax, SYSCALL_FCNTL + syscall + pop rsi + pop rdx + cmp eax, 0 + jne FT_READ_ERROR + + mov rax, SYSCALL_READ syscall ret +FT_READ_ERROR: + mov rax, -1 + ret +FT_READ_NO_SIZE: + xor rax, rax + ret @@ -12,8 +12,36 @@ global ft_write -; int ft_write(int, const void*, size_t); +%define F_GETFD 1 +%define SYSCALL_WRITE 0x2000004 +%define SYSCALL_FCNTL 0x200005c + +; int ft_write(int rdi, const void *rsi, size_t rdx); ft_write: - mov rax, 0x2000004 + cmp rdx, 0 + je FT_WRITE_NO_SIZE + cmp rdi, 0 + jl FT_WRITE_ERROR ; fd < 0 + cmp rsi, 0 + je FT_WRITE_ERROR ; buf == NULL + + push rdx + push rsi + xor rsi, rsi + mov esi, F_GETFD + mov rax, SYSCALL_FCNTL + syscall + pop rsi + pop rdx + cmp eax, 0 + jne FT_WRITE_ERROR + + mov rax, SYSCALL_WRITE syscall ret +FT_WRITE_ERROR: + mov rax, -1 + ret +FT_WRITE_NO_SIZE: + mov rax, 0 + ret @@ -6,7 +6,7 @@ /* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/11/22 02:02:24 by cacharle #+# #+# */ -/* Updated: 2019/11/25 03:29:53 by cacharle ### ########.fr */ +/* Updated: 2020/04/12 19:51:04 by charles ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,6 +20,116 @@ typedef struct s_list struct s_list *next; } t_list; + +int* +create_data_elem(int data) +{ + int *data_ptr = malloc(sizeof(int)); + if (data_ptr == NULL) + return (NULL); + *data_ptr = data; + return data_ptr; +} + +t_list* +create_elem(int data) +{ + t_list *new = malloc(sizeof(t_list)); + if (new == NULL) + return NULL; + if ((new->data = create_data_elem(data)) == NULL) + return (NULL); + new->next = NULL; + return new; +} + +static void +push_front(t_list **lst_ptr, t_list *new_front) +{ + if (lst_ptr == NULL || new_front == NULL) + return ; + new_front->next = *lst_ptr; + *lst_ptr = new_front; +} + +static t_list* +reverse(t_list *list) +{ + if (list == NULL || list->next == NULL) + return list; + t_list *tmp = reverse(list->next); + list->next->next = list; + list->next = NULL; + return tmp; +} + +t_list* +list_from_format(char *fmt) +{ + t_list *head = NULL; + + while (fmt != NULL && *fmt) + { + int n = (int)strtol(fmt, &fmt, 10); + t_list *elem = create_elem(n); + push_front(&head, elem); + } + return reverse(head); +} + +t_list* +list_dup(t_list *list) +{ + t_list *dup_head = NULL; + + while (list != NULL) + { + t_list *tmp = create_elem(*(int*)list->data); + push_front(&dup_head, tmp); + } + return reverse(dup_head); +} + +int +list_cmp(t_list *l1, t_list *l2) +{ + if (l1 == NULL && l2 == NULL) + return 0; + if (l1 == NULL) + return -1; + if (l2 == NULL) + return 1; + if (l1->data == NULL) + return -1; + if (l2->data == NULL) + return 1; + if (*(int*)l1->data != *(int*)l2->data) + return *(int*)l1->data - *(int*)l2->data; + return list_cmp(l1->next, l2->next); +} + +void +list_print(t_list *list) +{ + while (list != NULL) + { + printf("[%d] -> ", *(int*)list->data); + list = list->next; + } + printf("(null)"); +} + +void +list_destroy(t_list *list) +{ + if (list == NULL) + return ; + list_destroy(list->next); + if (list->data != NULL) + free(list->data); + free(list); +} + int ft_strlen(char *); char *ft_strcpy(char *dst, const char *src); int ft_strcmp(const char *s1, const char *s2); @@ -31,6 +141,26 @@ int ft_atoi_base(const char*, const char*); void ft_list_push_front(t_list **begin_list, void *data); int ft_list_size(t_list *begin_list); void ft_list_sort(t_list **begin_list, int (*cmp)()); +void ft_list_remove_if(t_list **begin_list, void *data_ref, int (*cmp)(), void (*free_fct)(void*)); + +int compar(void *a, void *b) +{ + printf("---\n"); + printf("a = %p, b = %p\n", a, b); + printf("*a = %d, *b = %d\n", *(int*)a, *(int*)b); + int c = *(int*)a - *(int*)b; + printf("ret %d\n", c); + return c; +} + +void free_fct(void *data) +{ + printf("free: %p\n", data); + printf("free data %d\n", *(int*)data); + free(data); + printf("end free\n"); + fflush(stdout); +} int main() { @@ -66,12 +196,30 @@ int main() /* printf("%d\n", h); */ /* printf("%s\n", h); */ /* free(h); */ - /* */ + /* printf("%d\n", check_base("01")); */ /* printf("%d\n", ft_atoi_base(" \t\n\r\v\f\r 10\t0101001", "01")); */ - printf("%d\n", ft_atoi_base("01", "")); /* printf("_%d_\n", ft_atoi_base(" 755x+", "01234567")); */ + + /* system("vmmap a.out"); */ + /* t_list *a = list_from_format("-1 2 3 98 1234 12 123 4 123 -123 2 5 6 0 1 3 4"); */ + /* t_list *a = list_from_format("1"); */ + /* t_list *a = NULL; */ + /* printf("%d: ", ft_list_size(a)); list_print(a); putchar('\n'); */ + /* ft_list_sort(&a, compar); */ + /* printf("%d: ", ft_list_size(a)); list_print(a); putchar('\n'); */ + + t_list *a = list_from_format("1 2 3 4 1 2 3 1"); + int data_ref = 1; + printf("f: %p\n", a->data); + /* free(a->data); */ + printf("%p\n", &data_ref); + list_print(a); putchar('\n'); + ft_list_remove_if(&a, &data_ref, compar, free_fct); + list_print(a); putchar('\n'); + + list_destroy(a); return 0; } |
