0

作为一项任务,我必须阅读汇编代码并编写其高级 C 程序。这种情况下的结构是一个switch语句,因此对于每种情况,汇编代码都被翻译成 C 代码中的情况。以下只是其中一种情况。如果你能帮我解释一下,它应该能让我更好地理解其余的案例。

p1 is in %ebp+8
p2 is in %ebp+12
action is in %ebp+16
result is in %edx

...
.L13:
    movl 8(%ebp), %eax    # get p1
    movl (%eax), %edx     # result = *p1?
    movl 12(%ebp), %ecx   # get p2
    movl (%ecx), %eax     # p1 = *p2
    movl 8(%ebp), %ecx    # p2 = p1
    movl %eax, (%ecx)     # *p1 = *p2?
    jmp .L19              #jump to default
...
.L19
    movl %edx, %eax       # set return value

当然,这些评论是我添加的,试图理解它,但它让我更加困惑。这是要交换的意思吗?可能不是; 格式会有所不同。第 2 行和第 6 行到底发生了什么?如果它是返回值,为什么 %edx 只更改一次这么早?请回答一些解释此代码的准则。

4

1 回答 1

4

上面的代码片段是(IMO 损坏的)AT&T 语法中的 x86_32 程序集。

AT&T 语法为每个操作数附加一个大小后缀。

movl表示 32 位操作数。(l for long)
movw表示 16 位操作数 (w for word)
movb表示 8 位操作数 (b for byte)

操作数的顺序颠倒了,所以目标在右边,源在左边。
这与几乎所有其他编程语言相反。

寄存器名称以 a 为前缀,%以区别于变量名称。如果寄存器被括号括()起来,则表示使用的是寄存器指向的内存地址,而不是寄存器本身内部的值。
这是有道理的,因为 EBP 被用作指向堆栈帧的指针。
Stackframes 用于访问函数中的参数和局部变量。

而不是写成:mov eax, dword ptr [ebp+8] (Intel 语法)
AT&T 语法将其列为:movl 8(%ebp), %eax (gas 语法)

这意味着:将(ebp + 8)指向的内存地址的竞争放入eax。

这是翻译:

.L13:   <<-- label used as a jump target. 
    movl 8(%ebp), %eax    <<--  p1, stored at ebp+8 goes into EAX
    movl (%eax), %edx     <<-- p1 is a pointer, EDX = p1->next
    movl 12(%ebp), %ecx   <<-- p2, stored at ebp+12 goes in ECX
    movl (%ecx), %eax     <<-- p2 is (again) a pointer, EAX = p2->next
    movl 8(%ebp), %ecx    <<-- ECX = p1
    movl %eax, (%ecx)     <<-- p2->next = p1->next 
    jmp .L19              <<-- jump to exit 
...
.L19
    movl %edx, %eax       <<-- EAX is always the return value
                          <<-- return p1->data.

在 x86 上的所有许多调用约定中,函数的返回值都放入 EAX 寄存器。(如果是 INT64,则为 EAX:EDX)

在散文中:p1 和 p2 是指向数据的指针,在这个数据中是指向指针的指针。
这段代码看起来像是在操作一个链表。
p2->next设置为p1->next
除此之外,该片段看起来不完整,因为一p2->next开始的任何内容都没有处理,因此您可能没有显示更多代码。

除了令人困惑的 AT&T 语法之外,它实际上是非常简单的代码。

在 C 中,代码如下所示:

(void *)p2->next = (void *)p1->next;

请注意,该代码效率非常低,并且没有像样的编译器(或人类)会生成此代码。

以下等价物会更有意义:

mov eax,[ebp+8]
mov ecx,[ebp+12]
mov eax,[eax]
mov [ecx],eax
jmp done

有关 AT&T 和 Intel 语法之间差异的更多信息,请参见此处:http ://www.ibm.com/developerworks/linux/library/l-gas-nasm/index.html

于 2013-10-13T17:12:05.630 回答