x86汇编问题

3
这是我的汇编程序,它只是一个交换*x和*y的函数。 因此,从main函数传递的第一个参数是x的地址,位于8(%ebp),第二个参数是y的地址,位于12(%ebp)。 该程序将交换x和y。 我需要7行才能完成这个操作。您能使其变为6行吗? 并且有一个条件,您只能使用%eax%ecx%edx这3个寄存器。 我思考了很久,但我无法将其缩短为6行。肯定有办法,不是吗? 这可能不是什么大问题,但如果能在6行内解决,我想知道如何做到。
movl 8(%ebp), %eax
movl (%eax), %ecx
movl 12(%ebp), %edx
movl (%edx), %eax
movl %ecx, (%edx)
movl 8(%ebp), %ecx
movl %eax, (%ecx)

行数是一个练习中的度量标准,但是程序越短并不一定意味着它运行得更快。特别是当你被限制使用寄存器的数量时,强迫你使用Andreas提供的Xor交换技巧。实际上,再增加一个寄存器会使操作速度更快。这是作业吗? - Pascal Cuoq
这是一个真正的问题还是一个代码高尔夫?对于一个真正的问题来说,“行数”听起来像是非常糟糕的度量标准,因为它既不符合速度优化也不符合代码大小优化这两个常见的优化目标。 - Suma
是的,这有点像作业..但不一定..只是让我思考一下..但如果有办法,我只是想知道~~就这样谢谢 - kevin
4个回答

3
你正在使用哪种汇编器,以及你的目标处理器是什么?
如果你正在使用MASM,那么你可以像这样向寄存器添加偏移量:
mov eax, ebp - 12
mov ecx, ebp - 8
mov ebp - 12, ecx
mov ebp - 8, eax

另外,您可以使用xchg指令,并在3行内完成:

mov eax, ebp - 12
xchg ebp - 8, eax
xchg ebp - 12, eax

这似乎很简单,也许我漏掉了什么?

1
我认为指向值的指针在堆栈中,而不是值本身。 - clstrfsck
目标是x86,汇编器是gas,我在标签中加入了这些信息。 - Pascal Cuoq
3
"Xchg"指令在计算指令数量方面确实有用,但在现代处理器上在此上下文中使用此指令有些荒谬:该指令意味着存在内存屏障。 - Pascal Cuoq

2

摩托罗拉语法不是我的强项,但我会尝试用5个指令来实现:

movl 8(%ebp), %eax
movl (%eax), %ecx
movl 12(%ebp), %edx
xchg (%edx), %ecx
movl %ecx, (%eax)

请参考Pascal关于短代码可能会更慢的评论。由于隐式的lock前缀,xchg %reg,(mem)很可能比重新加载地址要慢。


2

1
我明白了!这是基于异或交换技巧的。不过有点不同^^;答案是
movl    8(%ebp), %eax 
movl    (%eax), %ecx 
movl    12(%ebp), %edx 
xorl    (%edx), %ecx
xorl    %ecx, (%eax) 
xorl    %ecx, (%edx) 

像这样只使用一次内存访问。因为在x86中,源和目的地都不能使用同一条指令访问内存。每条指令只能有一个能够使用。所以我就是这样使用的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接