1

我正在尝试自学组装(出于好奇和学习的兴趣),并开发了一些从 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指令复制cxinto的值eax(我的编译器用来返回的值)。我这样做是因为如果我只使用MOV. 使用MOVZX可取吗?或者有没有更有效的方法我应该这样做?

您还会在我的代码中注意到i dd 5我最初的计划是,MOV cx, i但是当我尝试这样做时,我的编译器拒绝汇编。(MOVSX产生相同的结果)。所以我的第二个问题是,如何将 的值移动icx寄存器中?

4

3 回答 3

1

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

使用后ecx,该指令mov ecx, i可能会起作用-但您没有说明尝试该操作时遇到的实际错误。

于 2012-10-02T20:26:37.887 回答
1

您的代码效率不高,不。LOOP 指令已经过时并且很少使用了,因为它的性能不如简单地手动递减。

您可以通过与自身进行异或来将寄存器归零,然后您可以通过立即 ADD 将数字加载到其中。我不经常使用汇编,所以我没有牢牢掌握语法,不幸的是无法发布示例。

于 2012-10-02T20:27:48.540 回答
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
于 2012-10-02T20:30:44.573 回答