【问题标题】:Sorting C linked list in ASMx64 language用 ASMx64 语言对 C 链表进行排序
【发布时间】:2020-11-05 21:18:57
【问题描述】:

我正在尝试创建一个在程序集中对 C 链表进行排序的函数,但它不起作用,我不知道如何解决这个问题,我已经研究了几个小时,如果有人的话可以帮助它会很好。 所以我要创建的函数原型是:

void ft_list_sort(t_list **begin_list, int (*cmp)());

我正在处理的链表只是一个简单的基本列表:

typedef struct s_list {
    void            *data;
    struct s_list   *next;
} t_list;

这是我使用 cmets 的函数的汇编代码:

global ft_list_sort

section .text
ft_list_sort:
    mov r8,  [rdi]              ;put begin pointer in r8
    mov r10, rsi                ;put cmp function in r10

main_loop:
    cmp  r8,  0                 ;check if current list is null
    je   exit                   ;if null we are at the end of list so exit
    mov  r9,  [r8 + 8]          ;put current list -> next in r9
    push r9                     ;save the value in the stack
    jmp  sort_loop              ;jump to our second loop

main_loop_after:
    pop  r8                     ;current list = current list -> next
    jmp  main_loop

sort_loop:
    cmp  r9,  0                 ;check if loop list is null
    je   main_loop_after        ;if null we are at the end of list so jump back in main loop
    mov  rdi, [r8]              ;put current list data in rdi
    mov  rsi, [r9]              ;put loop list data in rsi
    call r10                    ;call cmp function
    cmp  rax, 0                 ;check the result
    ja   swap                   ;if above zero jump to swap

sort_loop_after:
    mov  rdx, [r9 + 8]
    mov  r9,  rdx               ;loop list = loop list -> next
    jmp  sort_loop              ;go back to begin of loop

swap:
    mov  rdx, rdi
    mov  rdi, rsi               ;swap rsi and rdi (current list data and loop list data)
    mov  rsi, rdx
    jmp  sort_loop_after        ;go back to the loop

exit:
    ret

我正在用这个 main 运行这个函数:

#include <stdio.h>
#include <stdlib.h> 
#include <string.h>
#include <errno.h>

typedef struct s_list 
    void            *data;
    struct s_list   *next;
} t_list;

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)());

t_list *lstnew(void *data) {
    t_list *newlist = malloc(sizeof(t_list));

    if (!newlist)
        return (NULL);
    newlist->data = data;
    newlist->next = NULL;
    return (newlist);
}

void lst_disp(t_list *lst) {
    while (lst) {
        printf("%d\n", (int)lst->data);
        lst = lst->next;
    }
}

void lst_clear(t_list **lst) {
    t_list *head = (*lst)->next;
    while (*lst) {
        free(*lst);
        *lst = head;
        if (head)
            head = head->next;
    }
}

int int_comp(void *n1, void* n2)
{
    return ((int)n1 - (int)n2);
}

int main(void) {
    t_list *list = lstnew((void*)1);
    ft_list_push_front(&list, (void*)10); //This function is to add a member to the list
    ft_list_push_front(&list, (void*)3);
    ft_list_push_front(&list, (void*)20);
    ft_list_push_front(&list, (void*)5);
    ft_list_push_front(&list, (void*)42);
    printf("before\n");
    lst_disp(list);
    printf("after\n");
    ft_list_sort(&list, &int_comp);
    lst_disp(list);
    lst_clear(&list);
    return (0);
}

它不会崩溃,但该函数什么也不做。 输出:

before
42
5
20
3
10
1
after
42
5
20
3
10
1

我试图在我的int_comp 函数中打印(int)n1 - (int)n2 的值,但它出现了段错误,所以我猜swap: 的寄存器值有问题,但我不知道是什么,谢谢你的帮助. 对于编译,我使用了一个 makefile,因为我将它与其他函数一起编译为一个库。 所以为了这个文件:

nasm -f elf64 ft_list_sort.s
ar rcs libasm_bonus.a ft_list_sort.o
gcc main.c libasm_bonus.a

如果你想看我推送my entire project on github的makefile。

【问题讨论】:

  • “不起作用”对我们没有帮助,它不是技术诊断。将其转储到您的调试器中并逐步查看问题所在。
  • 我在你的函数中没有看到你实际写入内存的任何地方,即没有mov [xxx], yyy,因此内存中的列表根本没有改变。您的 swap 在一些寄存器中移动,但实际上并未触及列表的结构。
  • @Fayeure:那么学习如何做到这一点是第一要务。这并不难,但是在不知道如何单步执行的情况下尝试在汇编中做任何事情会使开发过程变得非常缓慢和令人沮丧。
  • @Fayeure:不,不是。寄存器包含这些值的副本,而不是对它们的引用,并且操作寄存器中的值对内存没有任何影响。如果你想改变记忆,你必须存储,例如在将所需的新值放入rdi 之后执行mov [r8], rdi
  • 作为一个 C 类比,考虑long rdi; long *r8; rdi = *r8; rdi = 17; print(*r8);。这不会将*r8 设置为17

标签: c assembly linked-list x86-64 nasm


【解决方案1】:

正如@NateEldridge 所说,您的汇编代码实际上并没有向内存写入任何内容。

看来问题的核心在于这部分:

swap:
    mov  rdx, rdi
    mov  rdi, rsi               ;swap rsi and rdi (current list data and loop list data)
    mov  rsi, rdx
    jmp  sort_loop_after        ;go back to the loop

而不是在内存中交换列表的节点(这似乎是您想要做的,因为当cmp 函数指示错误的顺序时您会调用它) - 这会交换寄存器中的值。

【讨论】:

    猜你喜欢
    • 2011-01-02
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 2012-08-02
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多