The MASM Forum

General => The Campus => Topic started by: frktons on November 30, 2012, 06:01:50 AM

Title: Help for a MACRO
Post by: frktons on November 30, 2012, 06:01:50 AM
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
Title: Re: Help for a MACRO
Post by: nidud on November 30, 2012, 07:28:48 AM
deleted
Title: Re: Help for a MACRO
Post by: frktons on November 30, 2012, 07:38:56 AM
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.  :(
Title: Re: Help for a MACRO
Post by: nidud on November 30, 2012, 08:01:59 AM
deleted
Title: Re: Help for a MACRO
Post by: 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;
          ++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

Title: Re: Help for a MACRO
Post by: nidud on November 30, 2012, 08:12:45 AM
deleted
Title: Re: Help for a MACRO
Post by: frktons on November 30, 2012, 08:15:57 AM
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
Title: Re: Help for a MACRO
Post by: nidud on November 30, 2012, 08:19:39 AM
deleted
Title: Re: Help for a MACRO
Post by: frktons on November 30, 2012, 08:20:28 AM
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:
Title: Re: Help for a MACRO
Post by: nidud on November 30, 2012, 08:24:42 AM
deleted
Title: Re: Help for a MACRO
Post by: frktons on November 30, 2012, 08:34:54 AM
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.
Title: Re: Help for a MACRO
Post by: frktons on November 30, 2012, 08:59:55 AM
If anyone is interested, accluded is the final source
of the MACRO AreEQU16

Enjoy

Title: Re: Help for a MACRO
Post by: 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
Title: Re: Help for a MACRO
Post by: frktons on November 30, 2012, 09:04:50 AM
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
Title: Re: Help for a MACRO
Post by: nidud on November 30, 2012, 09:39:50 AM
deleted
Title: Re: Help for a MACRO
Post by: frktons on November 30, 2012, 11:12:25 AM
nidud, your code on my pc:


Intel(R) Core(TM)2 CPU          6600  @ 2.40GHz (SSE4)
---------------------------------------------------------
9054    cycles for XMM/pcmpeqd
9071    cycles for XMM/pcmpeqb
---------------------------------------------------------
9260    cycles for XMM/pcmpeqd
9047    cycles for XMM/pcmpeqb
---------------------------------------------------------
9046    cycles for XMM/pcmpeqd
9067    cycles for XMM/pcmpeqb
---------------------------------------------------------

Title: Re: Help for a MACRO
Post by: nidud on November 30, 2012, 11:51:45 AM
deleted
Title: Re: Help for a MACRO
Post by: frktons on November 30, 2012, 09:46:23 PM
Quote from: nidud on November 30, 2012, 11:51:45 AM
I will assume they are more or less the same, but since the mask returned from pmovmskb is from the 16 bytes, you may as well use the byte-cmp version.

Also, I used pcmpeqb and pcmpeqd in the test, and not pcmpgtb and pcmpgtd, so maybe that gives other results.


The road to Greater than or Less than should be
longer, so I forecast the performance will be Less than
PCMPEQD/B. 
Title: Re: Help for a MACRO
Post by: frktons on November 30, 2012, 10:56:47 PM
The new partial ISGTLT16A MACRO with new syntax error
I'm unable to see.

;-------------------------------------------------------------------------------
; Macro_ISGTLT16A.asm
; http://masm32.com/board/index.php?topic=983.0
;-------------------------------------------------------------------------------
; Test the difference between two 16 bytes long strings and display the result.
; The strings have to be 16 bytes boundaries aligned.
;
; 30/Nov/2012 - MASM FORUM - frktons
;-------------------------------------------------------------------------------

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

;-------------------------------------------------------------------------------
; MACRO to verify the greater of two 16 bytes long aligned strings
;-------------------------------------------------------------------------------
ISGTLT16A MACRO PtrValue1, PtrValue2   ;; 2 PTR value to the strings

   LOCAL   RetCode, ISNOTGT2, EndCheck

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

       mov  eax, PtrValue2
       movdqa xmm2, [eax]

       pcmpgtd xmm1, xmm2
       pmovmskb  eax, xmm1
       
       .if  ((bit ax, 15) == 0)

          jmp  short ISNOTGT2

       .endif
       
       mov  eax, YesEQU   
       mov  RetCode, eax
       jmp  short EndCheck

   ISNOTGT2:

       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
align 16
Str2        db  "Prima stringa di",0,0,0,0
PtrStr2     dd  Str2

.code

start:

print "---------------------------------------------------------", 13, 10
      print " Testing two strings for GT / LT through two", 13, 10
      print " xmm registers", 13, 10
print "---------------------------------------------------------", 13, 10     
      print " Test with PCMPGTD in a macro - ISGTLT16A -", 13, 10, 13, 10
      print " The two strings are ", 13, 10, 13, 10
      print " 1. "
      print PtrStr1, 13, 10
      print " 2. "
      print PtrStr2, 13, 10, 13, 10
      print " and the first is "
     
      .if   ISGTLT16A(PtrStr1, PtrStr2)
     
            print "Greater than the second one", 13, 10, 13, 10
           
      .else
     
            print "Less than the second one", 13, 10, 13, 10
                 
      .endif
           
print "---------------------------------------------------------", 13, 10


      inkey

      exit
     
end start


Quote
Microsoft (R) Macro Assembler Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

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

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

F:\Esempi_PGM\Assembly\Macro_ISGTLT16A.asm(90) : error A2008:syntax error : ,
ISGTLT16A(21): Macro Called From
  F:\Esempi_PGM\Assembly\Macro_ISGTLT16A.asm(90): Main Line Code
F:\Esempi_PGM\Assembly\Macro_ISGTLT16A.asm(90) : fatal error A1011:directive mus
t be in control block
ISGTLT16A(25): Macro Called From
  F:\Esempi_PGM\Assembly\Macro_ISGTLT16A.asm(90): Main Line Code
_
Assembly Error

Someone who sees better than me could please let me know where
I mispelled something.

Thanks
Title: Re: Help for a MACRO
Post by: jj2007 on November 30, 2012, 11:19:53 PM
.if  ((bit ax, 15) == 0)

Doesn't look like assembler. Do you mean this?
bt ax, 15
.if  Zero?

Title: Re: Help for a MACRO
Post by: frktons on November 30, 2012, 11:38:55 PM
Quote from: jj2007 on November 30, 2012, 11:19:53 PM
.if  ((bit ax, 15) == 0)

Doesn't look like assembler. Do you mean this?
bt ax, 15
.if  Zero?



Yes JJ, that's what I meant. This mean I can't use
.if with the bt opcode test?
Title: Re: Help for a MACRO
Post by: jj2007 on December 01, 2012, 12:26:33 AM
You can use almost everything, provided you defined it before and it does not clash with defined keywords.

include \masm32\include\masm32rt.inc
btx MACRO Reg, Bit
  bt Reg, Bit
  EXITM <Carry?>
ENDM
.code
start:
mov ebx, -1
bt ebx, 15
.if  Carry?
print "Set", 13, 10
.else
print "Not set", 13, 10
.endif
.if btx(ebx, 15)
print "Set", 13, 10
.else
print "Not set", 13, 10
.endif
inc ebx
bt ebx, 15
.if  Carry?
print "Set", 13, 10
.else
print "Not set", 13, 10
.endif
.if btx(ebx, 15)
inkey "Set"
.else
inkey "Not Set"
.endif
exit
end start
Title: Re: Help for a MACRO
Post by: frktons on December 01, 2012, 01:41:26 AM
Quote from: jj2007 on December 01, 2012, 12:26:33 AM
You can use almost everything, provided you defined it before and it does not clash with defined keywords.

include \masm32\include\masm32rt.inc
btx MACRO Reg, Bit
  bt Reg, Bit
  EXITM <Carry?>
ENDM
.code
start:
mov ebx, -1
bt ebx, 15
.if  Carry?
print "Set", 13, 10
.else
print "Not set", 13, 10
.endif
.if btx(ebx, 15)
print "Set", 13, 10
.else
print "Not set", 13, 10
.endif
inc ebx
bt ebx, 15
.if  Carry?
print "Set", 13, 10
.else
print "Not set", 13, 10
.endif
.if btx(ebx, 15)
inkey "Set"
.else
inkey "Not Set"
.endif
exit
end start


Thanks Jochen. A little bit every day, in a couple of months
I hope I'll get what I need to write properly written MACROS.
:-)

By the way I finished ISGTLT16A, to compare two 16 bytes aligned strings
or two chunks of bigger strings/files/whatever with the alignement required.
The ISGTLT16U does the same with unaligned chunks.

Quote
---------------------------------------------------------
Testing two strings for GT / LT using two
xmm registers
---------------------------------------------------------
Test with PCMPGTD in a macro - ISGTLT16A -

The two strings are

1. Prima stringa da
2. Prima stringa di

and the first is Less than the second one

---------------------------------------------------------
Press any key to continue ...
Title: Re: Help for a MACRO
Post by: dedndave on December 01, 2012, 06:37:18 AM
you can still do things like
bt ebx, 15
.if  Carry? || x==21 || eax==3
Title: Re: Help for a MACRO
Post by: frktons on December 01, 2012, 06:58:49 AM
Quote from: dedndave on December 01, 2012, 06:37:18 AM
you can still do things like
bt ebx, 15
.if  Carry? || x==21 || eax==3


Thanks Dave. I've been 2 years out of assembly or
computer languages whatsoever, so I've to relearn the few
things I learned here at the time.
Being a hobby now, I just do it when I've time, and
assembly needs a lot of it.
Title: Re: Help for a MACRO
Post by: jj2007 on December 01, 2012, 07:07:57 AM
Quote from: dedndave on December 01, 2012, 06:37:18 AM
you can still do things like
bt ebx, 15
.if  Carry? || x==21 || eax==3


Same effect:
.if  btx(ebx, 15) || x==21 || eax==3
Title: Re: Help for a MACRO
Post by: frktons on December 01, 2012, 09:09:08 AM
Quote from: jj2007 on December 01, 2012, 07:07:57 AM
Quote from: dedndave on December 01, 2012, 06:37:18 AM
you can still do things like
bt ebx, 15
.if  Carry? || x==21 || eax==3


Same effect:
.if  btx(ebx, 15) || x==21 || eax==3

That's cool.

Thanks
Title: Re: Help for a MACRO
Post by: qWord on December 01, 2012, 09:44:22 AM
Quote from: jj2007 on December 01, 2012, 07:07:57 AM.if  btx(ebx, 15)
.if ebx & (1 SHL 15)
Title: Re: Help for a MACRO
Post by: jj2007 on December 01, 2012, 05:58:09 PM
Quote from: qWord on December 01, 2012, 09:44:22 AM
.if ebx & (1 SHL 15)

Works but is two bytes longer ;-)
Title: Re: Help for a MACRO
Post by: dedndave on December 02, 2012, 03:52:16 AM
.if bh & 80h

:biggrin:
Title: Re: Help for a MACRO
Post by: jj2007 on December 02, 2012, 04:52:28 AM
Quote from: dedndave on December 02, 2012, 03:52:16 AM
.if bh & 80h

:t
Title: Re: Help for a MACRO
Post by: frktons on December 02, 2012, 09:48:25 AM
Quote from: jj2007 on December 01, 2012, 07:07:57 AM.if  btx(ebx, 15)

It's readable for my n00b's sight.

Quote from: qWord on December 01, 2012, 09:44:22 AM
.if ebx & (1 SHL 15) 8)

It's NOT readable for my n00b's sight.
In other words [sequence of instructions] what we do?
(1 SHL 15) is not a common syntax, I didn'know
it existed. What are we shifting left? Probably ebx, before
a compare, but exactly what this line does?  ::)

Quote from: dedndave on December 02, 2012, 03:52:16 AM
.if bh & 80h

This is readable as well.  :icon_eek:  :eusa_clap:
Title: Re: Help for a MACRO
Post by: jj2007 on December 02, 2012, 10:00:12 AM
Quote from: frktons on December 02, 2012, 09:48:25 AM
Quote from: qWord on December 01, 2012, 09:44:22 AM
.if ebx & (1 SHL 15) 8)

It's NOT readable for my n00b's sight.
In other words [sequence of instructions] what we do?
(1 SHL 15) is not a common syntax, I didn'know
it existed. What are we shifting left?

The "1", actually.
(1 shl 15) is 32768 or 100000000000000b, same as 2^15

I don't like the shl syntax either, but Masm doesn't understand 2^15 :(
Title: Re: Help for a MACRO
Post by: frktons on December 02, 2012, 10:07:17 AM
Quote from: jj2007 on December 02, 2012, 10:00:12 AM

The "1", actually.
(1 shl 15) is 32768 or 100000000000000b, same as 2^15

I don't like the shl syntax either, but Masm doesn't understand 2^15 :(

I have to confess I suspected it.

I didn't find in Intel manuals this possibility to shift a constant, is it
a feature of MASM?
Title: Re: Help for a MACRO
Post by: MichaelW on December 02, 2012, 10:09:18 AM
Yes, the shifting is done by the MASM "preprocessor" and the result is encoded as a constant.

.if ebx & (1 SHL 15)
.endif


00401000 F7C300800000           test    ebx,8000h
00401006 7400                   jz      loc_00401008


Title: Re: Help for a MACRO
Post by: frktons on December 02, 2012, 10:29:19 AM
Quote from: MichaelW on December 02, 2012, 10:09:18 AM
Yes, the shifting is done by the MASM "preprocessor" and the result is encoded as a constant.

.if ebx & (1 SHL 15)
.endif


00401000 F7C300800000           test    ebx,8000h
00401006 7400                   jz      loc_00401008



Thanks Michael, good to know I can do so many things with
MACROS, preprocessor engine, and so on.

Something I could use is:


P2_15  EQU 1 SHL 15 ; The Power of 2 ^ 15

....

.if  ebx & P2_15
     jmp ItsThere
.endif



at least it should be doable, and quite readable for my eyes.  :lol: