装配计数为零

时间:2012-10-02 20:22:02

标签: loops assembly mov

我正在努力教自己大会(出于好奇心和学习兴趣),并开发了一些从5到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寄存器中?

3 个答案:

答案 0 :(得分:1)

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

使用ecx后,指令mov ecx, i可能会有效 - 但您没有说出在尝试时遇到的实际错误。

答案 1 :(得分:1)

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

您可以通过将寄存器与自身进行异或来归零,然后您可以使用立即ADD将数字加载到其中。我没有太多使用汇编,所以我没有完整的语法,不幸的是不能发布一个例子。

答案 2 :(得分: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