汇编中的递归?

发布于 2024-09-04 07:16:17 字数 585 浏览 5 评论 0原文

我试图更好地掌握汇编,当我必须处理寄存器、弹出/推送等时,我对如何递归调用函数有点困惑。

我正在 C++ 中嵌入 x86 汇编。在这里,我试图创建一个方法,给定一个整数数组,它将构建一个包含这些整数的链接列表,按照它们在数组中出现的顺序。

我通过调用递归函数来做到这一点:

insertElem (struct elem *head, struct elem *newElem, int data) 

-head:列表的头部

-data:将插入到列表末尾的数字

-newElem:指向内存中将存储新元素的位置(数据字段)

我的问题是我不断覆盖寄存器而不是典型的链表。 例如,如果我给它一个数组 {2,3,1,8,3,9},我的链表将返回第一个元素(head),并且仅返回最后一个元素,因为在 head 被删除后,元素不断相互覆盖。不再为空。

所以这里我的链接列表看起来像这样: 2-->9 而不是 2-->3-->1-->8-->3-->9

我感觉我不知道如何组织和处理寄存器。 newElem 位于 EBX 中并且不断被重写。提前致谢!

I'm trying to get a better grasp of assembly, and I am a little confused about how to recursively call functions when I have to deal with registers, popping/pushing, etc.

I am embedding x86 assembly in C++. Here I am trying to make a method which given an array of integers will build a linked list containing these integers in the order they appear in the array.

I am doing this by calling a recursive function:

insertElem (struct elem *head, struct elem *newElem, int data) 

-head: head of the list

-data: the number that will be inserted at the end of a list

-newElem: points to the location in memory where I will store the new element (data field)

My problem is that I keep overwriting the registers instead of a typical linked list.
For example, if I give it an array {2,3,1,8,3,9} my linked-list will return the first element (head) and only the last element, because the elements keep overwriting each other after head is no longer null.

So here my linked list looks something like:
2-->9 instead of 2-->3-->1-->8-->3-->9

I feel like I don't have a grasp on how to organize and handle the registers. newElem is in EBX and just keeps getting rewritten. Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

緦唸λ蓇 2024-09-11 07:16:17

如果没有看过你的 asm 代码,很难给出答案。我的第一个想法是,处理链表时不需要递归函数。

无论如何,跨函数调用保留寄存器的一般方法是将它们压入堆栈并随后弹出:

;
; ebx = current element
;
TraverseList:

   ; If this is the end of the list we can skip the recursive invocation
   cmp [ebx+next], 0
   je NoNextElement

   push ebx               ; Save current element (ebx) on stack
     mov ebx, [ebx+next]  ; Put next element in ebx
     call TraverseList    ; Recursive invocation
   pop ebx                ; Restore current element (ebx) from stack

NoNextElement:

   ; Do stuff with the current element (ebx)
   ...
   ret

It's difficult to give an answer without having seen your asm code. My first thought is that there's no need for recursive functions when dealing with linked lists.

Anyway, the general way to preserve registers across function calls is to push them on the stack and pop them afterwards:

;
; ebx = current element
;
TraverseList:

   ; If this is the end of the list we can skip the recursive invocation
   cmp [ebx+next], 0
   je NoNextElement

   push ebx               ; Save current element (ebx) on stack
     mov ebx, [ebx+next]  ; Put next element in ebx
     call TraverseList    ; Recursive invocation
   pop ebx                ; Restore current element (ebx) from stack

NoNextElement:

   ; Do stuff with the current element (ebx)
   ...
   ret
聊慰 2024-09-11 07:16:17

对于任何与汇编程序相关的“如何”问题,最通用的答案是:gcc -S。如果您对任何事情有疑问,只需看看一个像样的 C 编译器如何将其转换为较低级别的代码。

在您的情况下,您需要在堆栈帧上维护局部变量。仅将寄存器用于在任何外部子例程调用后不需要保留的值。

The most generic answer to any assembler-related "how to" question is: gcc -S. If you're in doubt about anything, just take a look on how a decent C compiler translates this into a lower-level code.

In your case, you need to maintain your local variables on a stack frame. Use registers only for values that need not to survive after any external subroutine call.

夏の忆 2024-09-11 07:16:17

尝试像这样的东西作为你的asm代码

__asm{
        mov ebx, dword ptr[esp+4] //head
        mov ecx, dword ptr[esp+8] //newElem
        mov edx, dword ptr[esp+12] // data

    cmp [ebx+4], 0
    je NO_NEXT_ELEMENT

    mov ebx, [ebx+4]
    mov ecx, [ecx+4]

    push edx
    push ecx
    push ebx
    call insertElem
    pop ebx
    pop ecx
    pop edx


NO_NEXT_ELEMENT:


    mov dword ptr[ebx+4], ecx 
    mov dword ptr[ecx], edx
    mov [ecx+4], 0

    ret
}

编辑:刚刚运行这个并意识到这是行不通的。它给出访问冲突读/写位置错误。但希望它能给你一个开始,也许有人可以清理一下。

Try something like this as your asm code

__asm{
        mov ebx, dword ptr[esp+4] //head
        mov ecx, dword ptr[esp+8] //newElem
        mov edx, dword ptr[esp+12] // data

    cmp [ebx+4], 0
    je NO_NEXT_ELEMENT

    mov ebx, [ebx+4]
    mov ecx, [ecx+4]

    push edx
    push ecx
    push ebx
    call insertElem
    pop ebx
    pop ecx
    pop edx


NO_NEXT_ELEMENT:


    mov dword ptr[ebx+4], ecx 
    mov dword ptr[ecx], edx
    mov [ecx+4], 0

    ret
}

EDIT: Just ran this and realized that is doesn't work. It gives Access violation reading/writing location errors. But hopefully it gives you a start, maybe someone can clean it up a bit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文