2017-07-06 54 views
0

我对汇编很新,我一直在想是否有任何操作可以像EQU一样执行,但使用寄存器?例如: -EQU for non-immediates x86

Boink EQU EAX 

如果不存在这样的操作,有没有什么办法等同BoinkEAX,而不必使用RESB, RESD等等?

道歉,如果这个问题似乎有点愚蠢的你,并提前感谢你。

我正在使用NASM。

+3

你忘了提及你使用的汇编,以及它的手动不得不说些什么;) – Jester

+2

答案取决于你使用的汇编和平台。一些汇编程序支持这种事情,所以了解你使用哪一个是很重要的。 – fuz

+1

我试过一次,发现产生的代码非常混乱。永远不会再这样做。 –

回答

3

这个问题确实看起来有点愚蠢,主要是因为你的动机不清楚。你为什么想这样做?您的目标是让代码更具可读性,从本质上赋予符号(人类可读)名称以其他难以理解的注册名称?

如果是这样,您可以使用preprocessor macros。在块的顶部定义宏以引入符号名称,然后确保在块的末尾取消定义它以防止混淆。例如:

Max: 

    %define value1 edx 
    %define value2 ecx 
    %define result eax 

    sub value1, value2 
    sbb result, result 
    not result 
    and result, value1 
    add result, value2 

    %undef value1 
    %undef value2 
    %undef result 

    ret 

案件如果这可以使代码更易读。以上可以说是其中的一种情况。它还可以更容易地更改寄存器分配,当您使用(读取:基准测试)代码来确定最优分配策略时,这非常方便。

在MASM中,您可以执行与TEXTEQU directive - (例如,

value1 TEXTEQU <edx> 
value2 TEXTEQU <ecx> 
result TEXTEQU <eax> 

但是你必须be very careful with this。在真实的代码中(至少,真实的代码已经写成高效的,如果它不是高效的,为什么你要在汇编中编写它?),你几乎总是重用寄存器以达到多种目的。这意味着您的符号名称很快就会过时。你是否继续在整个代码中使用过时的名字?您是否为每个注册的别名多个符号名称,涵盖所有可能的用途?你是否继续定义,取消定义并重新定义寄存器的新符号名称?这些都不是好的选择,无论你做什么,你都会让代码变得更加混乱。因此,你通常看到的汇编程序员所做的就是在每条指令的旁边使用注释来解释这条指令正在发生什么。喜欢的东西:

; Uses branchless instructions to find the maximum of two integers. 
; Parameters: EDX == value1 
;    ECX == value2 
; Returns: Maximum integer value in EAX 
; Clobbers: EDX 
Max: 
    sub edx, ecx ; edx <= (edx - ecx) 
    sbb eax, eax ; eax <= (CF == 1) ? -1  : 0 
    not eax   ; eax <= (CF == 1) ? 0   : -1 
    and eax, edx ; eax <= (CF == 1) ? 0   : (edx - ecx) 
    add eax, ecx ; eax <= (CF == 1) ? (0 + ecx) : ((edx - ecx) + ecx) 
    ret 
+1

或甚至在注释中使用符号名称,以帮助跟踪哪个高级变量或表达式当前位于哪个寄存器中。 –