String Operations:

The form that strings are allocated in the .DATA section is as follows,
      MyString db "This is a string",0

 

Copy String(method 1):

A simple copy example shows how this is done, it is assumed that the dest buffer is large enough to receive the byte count in source.

source is the address of the of the source buffer to copy
dest is the address of the destination buffer
ln is the byte count to copy
    cld                  ; set direction flag forward
    mov esi, source      ; put address into the source index
    mov edi, dest        ; put address into the destination index
    mov ecx, ln          ; put the number of bytes to copy in ecx
  ; --------------------------------------------------
  ; 
repeat copying bytes from ESI to EDI until ecx = 0
  ; --------------------------------------------------
    rep movsb           

 In this example, MOVSB copies each byte from ESI to EDI and decrements ECX. The exit condition for the REP prefix is when ECX is decremented to zero.

Copy String(method 2):
When you copy a zero terminated string, you can write an algorithm that copies until it finds an ascii zero.
    cld                  ; clear direction flag to read forward
    mov esi, source      ; put address into the source index
    mov edi, dest            ; put address into the destination index

  label:
    lodsb                  ; 
load byte from source into AL and inc ESI
    stosb                  ; write AL to dest and inc EDI
    cmp al, 0            ; see if its an ascii zero
    jne label            ; read the next byte if its not

On Pentium and later processors, it is faster to use MOV/INC than LODSB or STOSB. This is done by "dereferencing" both ESI and EDI so that they function as memory addresses.

 

Copy String(method 3):

It should be noted that the direction flag cld does not effect this method and you can use any 32 bit registers when you are not using the string instructions.

    mov esi, source      ; put address into the source index
    mov edi, dest            ; put address into the destination index
  label:
    mov al, [esi]            ; 
copy byte at address in esi to al
    inc esi                  ; increment address in esi
    mov [edi], al            ; copy byte in al to address in edi
    inc edi                  ; increment address in edi
    cmp al, 0            ; see if its an ascii zero
    jne label            ; jump back and read next byte if not

This code is longer but faster on later processors with dual pipelines due to what is called pairing.

Macro Operations:

    A macro with parameters:

      RGB MACRO red, green, blue
        xor eax, eax
        mov al, blue    ; 
blue
        rol eax, 8
        mov al, green   ; 
green
        rol eax, 8
        mov al, red     ; 
red
      ENDM

 

Then you can set the three BYTE values as either 3 immediate numerical operands, three memory operands or three registers.
      RGB 125, 175, 225
or
      RGB Byte1, Byte2, Byte3
or
      RGB cl, ch, dl

When the macro is called in code, it expands the macro back up to the code you wrote with the parameters you passed to it in the correct places.


Macros differ from library modules n a number of important ways, each macro call directly inserts the macro code into the body of the code so if you call a macro ten times, you get the code ten times.

 

Local parameters in a macro
A problem arises if a MACRO has a label in it when the macro is called more than once, you get a duplicate label error. Fortunately there is a simple solution to the problem, MASM has a LOCAL directive that applies to macros that works by the assembler inserting a unique label in its place during the pre-processor stage so that the error does not occur.

This name LOCAL is ambiguous in MASM as MASM also uses the same term in a procedures to designate stack parameters. The two seperate usages should not be confused, a LOCAL in a MACRO has the following form,

MyMacro MACRO Parameter1, Parameter2 etc ...
  
LOCAL MyLabel
  ; asm code
  jmp MyLabel
  ; asm code
  MyLabel:
  ; other asm code
ENDM

MASM converts the LOCAL MyLabel to something like ?00001: and the next call to the macro will be ?00002 etc ... This ensures that there is no duplication error. LOCAL can be applied to variables as well.