2012-10-02 15 views
1

我想教自己大会(出于对学习的好奇和兴趣),并开发了一些代码,从五到0.这就是它所做的一切。我想知道下面的代码是否有效?装配数量为零

.386 
.model flat, stdcall 

.data 
i dd 5 

.code 
main: 
    MOV cx, 5 
    lp: 
    LOOP lp 
    MOVZX eax, cx 
RET 
END main 

请注意,我用的是MOVZX指令的cx值复制到eax(什么我的编译器使用返回)。 我这样做是因为我的程序不会组装,如果我只是使用MOV。是否使用MOVZX渴望?还是有更有效的方法我应该这样做?

你会注意到在我的代码中,我有i dd 5我原来的计划是MOV cx, i但我的编译器拒绝汇编,当我尝试。 (MOVSX产生相同的结果)。所以我的第二个问题是,如何将i的值移入cx寄存器?

回答

1

如果您正在编写32位目标,则使用ecx寄存器而不是16位cx寄存器。然后,您将可以使用mov eax, ecx,而汇编器不会抱怨操作数大小。另外,loop指令隐式使用ecx,因此您需要确保整个寄存器初始化为5,而不仅仅是低16位。

使用ecx之后,指令mov ecx, i可能会起作用 - 但是您没有说明在您尝试时发生的实际错误。

+0

酷,谢谢。我想我应该看看可用于我的不同的寄存器:) –

+1

寄存器根据它们的宽度有不同的名称。没有前缀的寄存器是16位宽。带有'E'前缀的寄存器是32位,'R'寄存器是64位。最重要的是,具有相同基本名称的寄存器共享低位位。如果您将某些东西加载到EAX中,然后加载到AX中,EAX的低16位将会改变。 – Wug

1

你的代码效率不高,没有。 LOOP指令是旧的,很少再使用,因为它不会像简单地手动递减那样执行。

您可以通过将它与自身进行异或来清零寄存器,然后可以使用即时ADD将其加载到该寄存器中。我不使用程序集,所以我没有坚实的语法,不幸的是无法发布示例。

+0

我知道'异或'的事情,但只是试验。我不知道'LOOP'很少用,谢谢你的回答。 –

1

这里有一个C的例子,就是类似于你:

#include <stdio.h> 

int i = 5; 

int 
main (int argc, char *argv[]) 
{ 
    while (--i >= 0) 
    ; 
    return 0; 
} 

这里是Visual Studio的汇编输出(CL/FA):

.386P 
include listing.inc 
if @Version gt 510 
.model FLAT 
else 
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE' 
_TEXT ENDS 
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA' 
_DATA ENDS 
CONST SEGMENT DWORD USE32 PUBLIC 'CONST' 
CONST ENDS 
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS' 
_BSS ENDS 
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS' 
_TLS ENDS 
FLAT GROUP _DATA, CONST, _BSS 
    ASSUME CS: FLAT, DS: FLAT, SS: FLAT 
endif 
PUBLIC _i 
_DATA SEGMENT 
_i DD 05H 
_DATA ENDS 
PUBLIC _main 
_TEXT SEGMENT 
_main PROC NEAR 
; File x.c 
; Line 7 
    push ebp 
    mov ebp, esp 
$L342: 
; Line 8 
    mov eax, DWORD PTR _i 
    sub eax, 1 
    mov DWORD PTR _i, eax 
    cmp DWORD PTR _i, 0 
    jl SHORT $L343 
; Line 9 
    jmp SHORT $L342 
$L343: 
; Line 10 
    xor eax, eax 
; Line 11 
    pop ebp 
    ret 0 
_main ENDP 
_TEXT ENDS 
END