News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Help for a MACRO

Started by frktons, November 30, 2012, 06:01:50 AM

Previous topic - Next topic

frktons

My experience with MACROS is about zero. I'm trying to
create a simple MACRO to verify that two 16 bytes long
strings are equal or not.

I've written almost the whole of it, but there are errors
during compilation about LOCAL variables and MACRO
directive.

Any help is welcome.


; ---------------------------------------------------------------------
; Macro_AreEQU16.asm
;
;-------------------------------------------------------------------------------
; Test the difference between two 16 bytes long strings and display the result
;
; 29/Nov/2012 - MASM FORUM - frktons
;-------------------------------------------------------------------------------

.nolist
include \masm32\include\masm32rt.inc
.686
.xmm

;-------------------------------------------------------------------------------
; MACRO to verify that two 16 bytes long string are equal
;-------------------------------------------------------------------------------
AreEQU16 MACRO PtrValue1, PtrValue2   ;; 2 PTR value to the strings

   YesEQU   EQU 1
   NotEQU   EQU 0
   LOCAL    RetCode
   
   .data?
       RetCode dd ?
   .code
       push eax
       
       mov  eax, PtrValue1
       movdqa xmm1, [eax]

       mov  eax, PtrValue2
       movdqa xmm2, [eax]

       pcmpeqd xmm1, xmm2
       pmovmskb  eax, xmm1
       cmp  ax, 0

       jne  NOT_EQ

       mov  eax, YesEQU   
       mov  RetCode, eax
       jmp  EndCheck

   NOT_EQ:

       mov  eax, NotEQU 
       mov RetCode, eax
       
   EndCheck:

       pop eax
 
   EXITM <RetCode>

ENDM

.data


align 16
Str1        db  "Prima stringa da",0,0,0,0
PtrStr1     dd  Str1
Str2        db  "Prima stringa da",0,0,0,0
PtrStr2     dd  Str2

.code

start:


print "---------------------------------------------------------", 13, 10
      print " Testing two strings for or equal through two", 13, 10
      print " xmm registers", 13, 10
print "---------------------------------------------------------", 13, 10     
      print " Test with PCMPEQD in a macro - AreEQU16", 13, 10, 13, 10
      print " The two strings are "
      .if   AreEQU16(PtrStr1, PtrStr2)
            print "Equal", 13, 10, 13, 10
      .else
            print "NOT Equal", 13, 10, 13, 10     
      .endif     
print "---------------------------------------------------------", 13, 10


      inkey

      exit
     
end start


This is the error I get:
Quote
Microsoft (R) Macro Assembler Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

Assembling: F:\Esempi_PGM\Assembly\Macro_AreEQU16.asm

***********
ASCII build
***********

F:\Esempi_PGM\Assembly\Macro_AreEQU16.asm(79) : error A2012:PROC, MACRO, or macr
o repeat directive must precede LOCAL
AreEQU16(4): Macro Called From
  F:\Esempi_PGM\Assembly\Macro_AreEQU16.asm(79): Main Line Code
_
Assembly Error


Frank
There are only two days a year when you can't do anything: one is called yesterday, the other is called tomorrow, so today is the right day to love, believe, do and, above all, live.

Dalai Lama

nidud

#1
deleted

frktons

Quote from: nidud on November 30, 2012, 07:28:48 AM
AreEQU16 MACRO PtrValue1, PtrValue2   ;; 2 PTR value to the strings
   LOCAL   RetCode;,NOT_EQ,EndCheck
   YesEQU   EQU 1
   NotEQU   EQU 0


Thanks nidud, there is an extra ";" that I've got rid of,
now it compiles, but... doesn't work.  ::)

When the MACRO is executed, the program freezes.  :(
There are only two days a year when you can't do anything: one is called yesterday, the other is called tomorrow, so today is the right day to love, believe, do and, above all, live.

Dalai Lama

nidud

#3
deleted

CommonTater

I don't know how much help this is for ASM...
But the usual way is to take the two strings character by character,
subtract one from the other and return on the first non 0 value you get...

In C...


char IsEqual(char* str1, char* str2)
  {
     char cmp;                            // comparison result variable

     while (*str1 && *str2)       // bail out if you hit a 0 at the end of a string.
       {
           cmp = *str1 - *str2
           if(cmp)                         // exit the loop on non-0 comparison
             break;
          ++str1;
          ++str2;
       }

     return cmp;                       // return the comparison value  >0 means string 1 sorts before string 2
   }                                         //  0  means they're the same,  < 0 means string 2 sorts before string 1


nidud

#5
deleted

frktons

Quote from: nidud on November 30, 2012, 08:01:59 AM
I'm not an expert on these things, but maybe the RetCode could be declared outside the macro as a global?

It is used in other MACROS and it works the way I put it,
maybe is something different.

Quote from: CommonTater on November 30, 2012, 08:07:39 AM
I don't know how much help this is for ASM...
But the usual way is to take the two strings character by character,
subtract one from the other and return on the first non 0 value you get...

In C...


char IsEqual(char* str1, char* str2)
  {
     char cmp;                            // comparison result variable

     while (*str1 && *str2)       // bail out if you hit a 0 at the end of a string.
       {
           cmp = *str1 - *str2
           if(cmp)                         // exit the loop on non-0 comparison
             break;
       }

     return cmp;                       // return the comparison value  >0 means string 1 sorts before string 2
   }                                         //  0  means they're the same,  < 0 means string 2 sorts before string 1



There are Assembly routines that do the same as the C code,
and other that do something different, the latter is what I've
already used and trying to implement as a MACRO.

Quote from: nidud on November 30, 2012, 08:12:45 AM
It fails on PtrStr2.
I inserted ALIGN 16, and it works:

align 16
Str1        db  "Prima stringa da",0,0,0,0
PtrStr1     dd  Str1
align 16
Str2        db  "Prima stringa da",0,0,0,0
PtrStr2     dd  Str2


Oh, yes, I forgot it. Thanks
There are only two days a year when you can't do anything: one is called yesterday, the other is called tomorrow, so today is the right day to love, believe, do and, above all, live.

Dalai Lama

nidud

#7
deleted

frktons

Now everything seems to work, except for the logic,
it gives erroneus result.
Quote
---------------------------------------------------------
Testing two strings for or equal through two
xmm registers
---------------------------------------------------------
Test with PCMPEQD in a macro - AreEQU16

The two strings are NOT Equal

---------------------------------------------------------

while the two strings are equals.  :lol:
There are only two days a year when you can't do anything: one is called yesterday, the other is called tomorrow, so today is the right day to love, believe, do and, above all, live.

Dalai Lama

nidud

#9
deleted

frktons

Quote from: nidud on November 30, 2012, 08:24:42 AM
cmp ax,-1

OK - I used:

       cmp  ax, 0FFFFh


and now it seems to work.

Quote
---------------------------------------------------------
Testing two strings for equal/NOT equal through two
xmm registers
---------------------------------------------------------
Test with PCMPEQD in a macro - AreEQU16 -

The two strings are Equal

---------------------------------------------------------

Thanks for your help. I'll do some tests and after I'll prepare the
MACRO for GTLT.
There are only two days a year when you can't do anything: one is called yesterday, the other is called tomorrow, so today is the right day to love, believe, do and, above all, live.

Dalai Lama

frktons

If anyone is interested, accluded is the final source
of the MACRO AreEQU16

Enjoy

There are only two days a year when you can't do anything: one is called yesterday, the other is called tomorrow, so today is the right day to love, believe, do and, above all, live.

Dalai Lama

jj2007

Caution with unaligned strings. Use movdqu or movups.

       mov  eax, PtrValue1
       movdqu xmm1, [eax]

       mov  eax, PtrValue2
       movdqu xmm2, [eax]

       pcmpeqd xmm1, xmm2
       pmovmskb  eax, xmm1
       cmp  ax, 0ffffh

frktons

Quote from: jj2007 on November 30, 2012, 09:00:30 AM
Caution with unaligned strings. Use movdqu or movups.

       mov  eax, PtrValue1
       movdqu xmm1, [eax]

       mov  eax, PtrValue2
       movdqu xmm2, [eax]

       pcmpeqd xmm1, xmm2
       pmovmskb  eax, xmm1
       cmp  ax, 0ffffh


Good idea Jochen, of course you are thinking about a future
standard use, like in a MACROS library, where the generalization
counts.

I was only thinking about learning how to write a MACRO and
have a fast code, your suggestion is something I forgot to consider.
:t
There are only two days a year when you can't do anything: one is called yesterday, the other is called tomorrow, so today is the right day to love, believe, do and, above all, live.

Dalai Lama

nidud

#14
deleted