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
deleted
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. :(
deleted
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
deleted
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
deleted
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:
deleted
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.
If anyone is interested, accluded is the final source
of the MACRO AreEQU16
Enjoy
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
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
deleted
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
---------------------------------------------------------
deleted
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 thanPCMPEQD/B.
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
.if ((bit ax, 15) == 0)
Doesn't look like assembler. Do you mean this?
bt ax, 15
.if Zero?
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?
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
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 ...
you can still do things like
bt ebx, 15
.if Carry? || x==21 || eax==3
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.
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
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
Quote from: qWord on December 01, 2012, 09:44:22 AM
.if ebx & (1 SHL 15)
Works but is two bytes longer ;-)
.if bh & 80h
:biggrin:
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:
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 :(
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?
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
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: