Question

I am trying to teach myself Assembly (out of curiosity and interest of learning) and have developed some code that counts from five to 0. Thats all it does. I was wondering if the following code was efficient?

.386
.model flat, stdcall

.data
i dd 5

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

Notice that I use the MOVZX instruction to copy the value of cx into eax (what my compiler uses to return). I do this because my program won't assemble if I simply use MOV. Is using MOVZX desireable? Or is there a more efficient way I should be doing this?

You will notice also in my code that I have i dd 5 my original plan was to MOV cx, i but my compiler refuses to assemble when I attempt that. (MOVSX yields the same result). So my second question is, how can I move the value of i into the cx register?

Was it helpful?

Solution

If you're writing for a 32-bit target, then use the ecx register instead of the 16-bit cx register. Then, you will be able to use mov eax, ecx without the assembler complaining about operand sizes. Also, the loop instruction implicitly uses ecx so you'll want to make sure the whole register is initialised with 5, and not just the lower 16 bits.

After using ecx, the instruction mov ecx, i may work - but you didn't say what actual error you were getting when you tried that.

OTHER TIPS

Your code isn't very efficient, no. The LOOP instruction is old and rarely used anymore because it doesn't tend to perform as well as simply manually decrementing.

You can zero a register by XORing it with itself, and you can then load a number into it with an immediate ADD. I don't use assembly much, so I don't have the syntax down solidly and unfortunately can't post an example.

Here's a C example that's analogous to yours:

#include <stdio.h>

int i = 5;

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

Here's the Visual Studio assembler output (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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top