汇编 - 错误实施免费清单

时间:2012-03-11 21:12:32

标签: assembly x86

我读了一本书,给出了下一个例子: 有一个列表,每个成员在其中有四个第一个字节的下一个成员的地址。最后一个成员的值为0.它说下一个实现是错误的,我不明白为什么:

freeList
   mov eax, [ebp+8]
   cmp eax, 0
   jne cont
   ret
cont:
   mov ebx, [eax]
   mov [ebp+8], ebx
   push eax
   call free
   pop eax
   call freeList

(我不需要正确的实现,我有一个。我只需要了解这个有什么问题)

感谢。

2 个答案:

答案 0 :(得分:2)

错误实现的最后一行是call freeList。但是当(递归)调用完成时,它将尝试返回该行之后的不存在的代码。附加ret指令会使代码工作,但通常你会尝试避免这种情况,除非在调试代码时,有时候有助于查看所有中间调用。相反,您可以将call freeList; ret简化为简单的jmp freeList

调试高级代码的示例:

function freeList(list) {
    if (list) {
        var next = list->next;
        free(list);
        freeList(next);
    }
}

如果使用optimisations进行编译,编译器可能希望通过将freeList(next)复制到next并执行list来编写递归调用jmp,但这会破坏list的值。这意味着当您尝试调试该函数时,您无法分辨列表中的哪些元素已被释放。因此,当您尝试调试函数中的问题时,您可能希望禁用此优化。

答案 1 :(得分:0)

假设这是一个函数,不可能直接调用它,因为您需要在调用之前设置堆栈帧,然后在调用它之后展开帧。它也不保留EBX,这与大多数系统ABI相反(只有EAX,ECX和EDX是临时寄存器)

如果这是内联代码,则需要解开当前帧(不是这样)。