The MASM Forum

General => The Campus => Topic started by: sergeyn on April 15, 2014, 08:19:51 AM

Title: Help creating macro to duplicate instructions
Post by: sergeyn on April 15, 2014, 08:19:51 AM
Hi,
I'm struggling to create a macro which duplicates instructions:
what I want to achieve is instead of writing this:
mov ymm1, [rax + 32*0]
mov ymm2, [rax + 32*1]
mov ymm3, [rax + 32*2]

I want to write like this:

DUPINSTR <mov ymm&i, [rax + 32*(&i+1)]>

How do I create such a macro ?

Thanks
Title: Re: Help creating macro to duplicate instructions
Post by: jj2007 on April 15, 2014, 09:00:26 AM
Like this, for example (with xmm because my CPU doesn't know about ymm):

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

DUPINSTR MACRO diLine, range
LOCAL isdots, iseq, is, ctStart, ctEnd, ct, tmp$, di$, diR$
  iseq INSTR <range>, <=>
  isdots INSTR <range>, <..>
  tmp$ SUBSTR <range>, iseq+1, isdots-iseq-1
  ctEnd SUBSTR <range>, isdots+2
  ct=ctEnd-tmp$
  ctStart=tmp$
  REPEAT ct
   di$ CATSTR <diLine>, <  >
   is INSTR <diLine>, <&i>
   While is
      diR$ SUBSTR di$, is+2
      diL$ SUBSTR di$, 1, is-1
      di$ CATSTR diL$, %ctStart, diR$
      is INSTR di$, <&>
   ENDM
   % echo ## di$
   di$
   ctStart=ctStart+1
  ENDM
ENDM

.code
TestArray   dq 100h, 200h, 300h, 400h, 500h, 600h, 700h, 800h, 900h, 1000h

start:
  mov eax, offset TestArray
  int 3   ; for Olly
  ; DUPINSTR <mov ymm&i, [rax + 32*(&i+1)]>
  DUPINSTR <movlps xmm&i, qword ptr [eax + 32*(&i+1)]>, i=0..3
  exit

end start

<ModuleEntryPoint>  Ú$  B8 00104000       mov eax, 00401000
00401055            ³.  CC                int3
00401056            ³.  0F1240 20         movlps xmm0, [eax+20]
0040105A            ³.  0F1248 40         movlps xmm1, [eax+40]
0040105E            ³.  0F1250 60         movlps xmm2, [eax+60]
00401062            ³.  6A 00             push 0                                 ; ÚExitCode = 0
00401064            À.  E8 01000000       call <jmp.&kernel32.ExitProcess>       ; ÀKERNEL32.ExitProcess
Title: Re: Help creating macro to duplicate instructions
Post by: sergeyn on April 15, 2014, 09:07:31 AM
Thank you very much, that works.

However, to make it more generic , do you think it is possible to support subscripts like this xmm&i+1  ?  Or maybe written like this : xmm&%i+1 ? Just some way to get computed register index.

Another question- why doesn't this code work:

expand macro text,i
  text
endm

...

expand <mov xmm&i,xmm&i>, 2

Thanks.
Title: Re: Help creating macro to duplicate instructions
Post by: jj2007 on April 15, 2014, 09:15:01 AM
Works with ML 6.14 and 6.15 but not with higher ML versions or JWasm:

  DUPINSTR <movlps xmm(&i+1), qword ptr [eax + 32*(&i+1)]>, i=0..3

Re expand: Why should it work?
Title: Re: Help creating macro to duplicate instructions
Post by: sergeyn on April 15, 2014, 09:24:03 AM
QuoteWorks with ML 6.14 and 6.15 but not with higher ML versions or JWasm
No way to make it work with ML 12 ?

QuoteWhy should it work?
Because '&' is a text substitution operator and there is a variable 'i' inside macro 'expand' ?

Thanks.
Title: Re: Help creating macro to duplicate instructions
Post by: qWord on April 15, 2014, 09:51:58 AM
Quote from: sergeyn on April 15, 2014, 09:24:03 AMBecause '&' is a text substitution operator and there is a variable 'i' inside macro 'expand' ?
As you said right, it does substitute text: search string x an replace it with text y. A simple solution that might not look that intuitive is:
e macro expr
    EXITM %expr
endm

DUPINSTR macro iStart:=<0>,iEnd:req,iIncr:=<1>,txt:=<>
    tmpMacro macro i
    %   txt
    endm
    dupi_cntr = iStart
    WHILE dupi_cntr LE iEnd
        tmpMacro %dupi_cntr
        dupi_cntr = dupi_cntr + iIncr
    ENDM
endm
;...
DUPINSTR 0,6,1,<movaps xmm&e(&i+1), OWORD ptr [eax + 32*&i]>

If evaluation is needed, use "&e(expression)". Remarks that the angle brackets <> are needed.
(you might change the macro name "e"...)
Title: Re: Help creating macro to duplicate instructions
Post by: sergeyn on April 15, 2014, 09:54:27 AM
Thank you so much!

You saved my day!

Title: Re: Help creating macro to duplicate instructions
Post by: qWord on April 15, 2014, 10:02:27 AM
Addendum: the exclamation mark is not needed: "&e(&i+1) also works.
Title: Re: Help creating macro to duplicate instructions
Post by: jj2007 on April 15, 2014, 03:15:24 PM
Burning the midnight oil, he?
:t
Title: Re: Help creating macro to duplicate instructions
Post by: sergeyn on April 17, 2014, 12:51:42 AM
Hi Again

Exactly the last version you've posted gives me an error

error A2006: undefined symbol : dupi_cntr

any clue ?

Thanks.

Edit:
This works for me:
expand macro iStart:req,iEnd:req,txt:req
    local ii
    ii = iStart
    WHILE ii LE iEnd
        for i,<%ii>
            %   txt
   endm
        ii = ii + 1
    ENDM
endm

I really want to understand how preprocessor works. If you have a clue, please enlighten me why this doesn't work:

expand macro iStart:req,iEnd:req,txt:req
    local i
    i = iStart
    WHILE i LE iEnd
        %   txt
        i = i + 1
    ENDM
endm

and this doesn't work either:

expand macro i:req,iEnd:req,txt:req
    WHILE i LE iEnd
        %   txt
        i = i + 1
    ENDM
endm


Thanks again!
Title: Re: Help creating macro to duplicate instructions
Post by: qWord on April 17, 2014, 01:51:47 AM
Quote from: sergeyn on April 17, 2014, 12:51:42 AMExactly the last version you've posted gives me an error

error A2006: undefined symbol : dupi_cntr

any clue ?
probably you used nonnumeric input for first macro parameter thus dupi_cntr is never assigned/created.

Quote from: sergeyn on April 17, 2014, 12:51:42 AMwhy this doesn't work:

expand macro iStart:req,iEnd:req,txt:req
    local i
    i = iStart
    WHILE i LE iEnd
        %   txt
        i = i + 1
    ENDM
endm
the expansion operator as first char. in line only substitute text macros - i is not a text macro.
Quote from: sergeyn on April 17, 2014, 12:51:42 AM
expand macro i:req,iEnd:req,txt:req
    WHILE i LE iEnd
        %   txt
        i = i + 1
    ENDM
endm
macro parameters are no variables - they will be substitute (text replacement) before evaluating the macro.

For more details see the MASM programmers guide chapter 9.
Title: Re: Help creating macro to duplicate instructions
Post by: sergeyn on April 17, 2014, 01:54:00 AM
QuoteFor more details see the MASM programmers guide chapter 9.
Could you share the link ?
Title: Re: Help creating macro to duplicate instructions
Post by: qWord on April 17, 2014, 02:02:29 AM
Quote from: sergeyn on April 17, 2014, 01:54:00 AMCould you share the link ?
search engine broken?  ;)

MASM_6.1_Manuals_[High_Quality_PDF].zip

EDIT: link removed.
Title: Re: Help creating macro to duplicate instructions
Post by: sergeyn on April 17, 2014, 02:06:07 AM
Thanks. Just wanted to have the exact version you are referring to. I've read a bunch of them and all are not providing too deep details about differences in numeric and textual variables and their use.
Title: Re: Help creating macro to duplicate instructions
Post by: jj2007 on April 17, 2014, 03:04:09 AM
Quote from: qWord on April 17, 2014, 02:02:29 AM
MASM_6.1_Manuals_[High_Quality_PDF].zip (http://www.4shared.com/zip/lCNJTTZk/MASM_61_Manuals_High_Quality_P.html)

Once you have bypassed all the ads, you may succeed in downloading MASM_6.1_Manuals_[High_Quality_PDF].exe

According to Eset (http://virusscan.jotti.org/en-gb/scanresult/ded3809da932b1bafa37255199eeb7ce60a9ea3a), it contains Win32/4Shared.R, a trojan.

PeView reveals that the exe has lots of imports from WinHTTP.dll, such as WinHttpReadData etc...

The limit for attachments is 512 k ;-)
Title: Re: Help creating macro to duplicate instructions
Post by: qWord on April 17, 2014, 03:43:25 AM
Quote from: jj2007 on April 17, 2014, 03:04:09 AM
Once you have bypassed all the ads, you may succeed in downloading MASM_6.1_Manuals_[High_Quality_PDF].exe

According to Eset (http://virusscan.jotti.org/en-gb/scanresult/ded3809da932b1bafa37255199eeb7ce60a9ea3a), it contains Win32/4Shared.R, a trojan.

PeView reveals that the exe has lots of imports from WinHTTP.dll, such as WinHttpReadData etc...

The limit for attachments is 512 k ;-)
yep, just copied that link from the old board...    :icon_confused:
Title: Re: Help creating macro to duplicate instructions
Post by: sergeyn on April 17, 2014, 04:05:09 AM
Funny situation ;)

Is this what you mean ?

http://people.sju.edu/~ggrevera/arch/references/MASM61PROGUIDE.pdf (http://people.sju.edu/~ggrevera/arch/references/MASM61PROGUIDE.pdf)
Title: Re: Help creating macro to duplicate instructions
Post by: qWord on April 17, 2014, 04:36:58 AM
Quote from: sergeyn on April 17, 2014, 04:05:09 AMIs this what you mean ?

http://people.sju.edu/~ggrevera/arch/references/MASM61PROGUIDE.pdf (http://people.sju.edu/~ggrevera/arch/references/MASM61PROGUIDE.pdf)
no.

I've temporarily uploaded it here: MASM_6.1_Manuals_High_Quality_PDF.zip (http://remixshare.com/download/w3mwr).
Title: Re: Help creating macro to duplicate instructions
Post by: jj2007 on April 17, 2014, 05:07:45 AM
Looks more trustworthy indeed :t

QuoteLEA    Load Effective Address
Calculates the effective address (offset) of the source memory operand and stores the result in the destination register. If the source operand is a direct memory address, the assembler encodes the instruction in the more efficient MOV reg,immediate form (equivalent to MOV reg, OFFSET mem).

Hmmm... my assemblers don't do that :(

QuoteA Word About Instruction Timings
...
• Smaller is often better. For example, the instructions
   dec  bx
   sub  bx, 1
accomplish the same thing and have the same timings on 80386/486 processors.
But the first instruction is 3 bytes smaller than the second, and so may reach the
processor faster.
• When possible, use the string instructions described in Chapter 5, "Defining and
Using Complex Data Types."
:greensml:
Title: Re: Help creating macro to duplicate instructions
Post by: Gunther on April 17, 2014, 08:04:30 PM
Hi qWord,

Quote from: qWord on April 17, 2014, 04:36:58 AM
I've temporarily uploaded it here: MASM_6.1_Manuals_High_Quality_PDF.zip (http://remixshare.com/download/w3mwr).

thank you for sharing the files.  :t

Gunther
Title: Re: Help creating macro to duplicate instructions
Post by: dedndave on April 17, 2014, 09:30:20 PM
the masm assembler does make a few substitutions for you   :P
    xchg    edx,eax  ;2 bytes
    xchg    eax,edx  ;1 byte
Title: Re: Help creating macro to duplicate instructions
Post by: qWord on April 18, 2014, 12:41:11 AM
Coming back to the topic, I just thought the macro could be generalized with a few modifications:
e macro expr
EXITM %expr
endm

FOR_ macro start:=<i=0>,condition:req,increment:=<i=i+1>,statement:=<>
% tmpMacro1 macro @SubStr(<&start>,1,@InStr(1,<&start>,<=>)-1)
% statement
endm
tmpMacro2 macro varName
LOCAL varName
start
WHILE condition
tmpMacro1 %varName
increment
ENDM
endm
%   tmpMacro2 @SubStr(<&start>,1,@InStr(1,<&start>,<=>)-1)
endm

-->
FOR_ k=0,k LT 7,k=k+1,<movdqa xmm&k,OWORD ptr [eax+k*OWORD]>
The variable name is freely selectable.
With some more lines and if one like that syntax:
FOR_ macro start:=<i=0>,condition:req,increment:=<i=i+1>,statements:=<>
for_vars TEXTEQU <>
for_expvars TEXTEQU <>
FOR arg,<&start>
for_vars TEXTEQU for_vars,<,>,@SubStr(<&arg>,1,@InStr(1,<&arg>,<=>)-1)
for_expvars TEXTEQU for_expvars,<,!%>,@SubStr(<&arg>,1,@InStr(1,<&arg>,<=>)-1)
ENDM
for_vars SUBSTR for_vars,2
for_expvars SUBSTR for_expvars,2
% tmpMacro1 macro &for_vars
FOR statement,<&statements>
% statement
ENDM
endm
tmpMacro2 macro varNames:VARARG
LOCAL varNames
FOR arg,<&start>
arg
ENDM
WHILE condition
% tmpMacro1 &for_expvars
FOR arg,<&increment>
arg
ENDM
ENDM
endm
% tmpMacro2 &for_vars
endm

-->
FOR_ i=0,i LT 7,i=i+1,\
<<movdqa xmm&e(i+1),OWORD ptr [eax+i*OWORD]>>
;...
FOR_ <i=0,j=7>,i LT 4,<i=i+1,j=j-1>,\
<\
<mov al,sz[i]>,\
<mov ah,sz[j]>,\
<mov sz[i],ah>,\
<mov sz[j],al>,\
>

:biggrin:

Title: Re: Help creating macro to duplicate instructions
Post by: sergeyn on April 18, 2014, 01:04:30 PM
Hello again,

Sorry for noobie questions - trying to extend the expand macro to support multi-line generation, and stuck with a very simple thing.

For debugging purposes trying to print the value of a variable:
work MACRO args:VARARG
work MACRO
local ii
ii = 999
ECHO !ii is: %ii
ENDM
work


I get this printed:

!ii is: ??0000

What am I doing wrong?
Title: Re: Help creating macro to duplicate instructions
Post by: jj2007 on April 18, 2014, 04:03:35 PM
work MACRO args:VARARG
local ii, tmp$
  ii = 999
  tmp$ CATSTR <!ii is: >, %ii, < with !args=>, <args>
  % echo tmp$
ENDM
Title: Re: Help creating macro to duplicate instructions
Post by: sergeyn on April 18, 2014, 08:52:21 PM
Ok, so my mistake was that everything after 'echo' is simply dumped to the screen without any substitutions.

How do you guys debug macros ? Is there a way to generate preprocessed file similar to what /P flag of cl.exe does?  The closest I found to see what's going on inside is "/Sa Maximize source listing". I basically want to see what the evaluator gets on it's input.

Another issue I've discovered - VARARG parameters can't properly parse commas, thus  a two argument call like <1,2>,<2,3> is seen as <1>,<2>,<3>,<4> by the vararg parsing code (as described in the docs). Do you know anyway to work around that ?

Thank you for you help!
Title: Re: Help creating macro to duplicate instructions
Post by: jj2007 on April 18, 2014, 10:20:02 PM
Quote from: sergeyn on April 18, 2014, 08:52:21 PMHow do you guys debug macros ?

With tmp$ CATSTR and .err as shown below.

QuoteAnother issue I've discovered - VARARG parameters can't properly parse commas, thus  a two argument call like <1,2>,<2,3> is seen as <1>,<2>,<3>,<4> by the vararg parsing code (as described in the docs). Do you know anyway to work around that ?

Masm separates arguments by commas, but you are not forced to use commas.
include \masm32\include\masm32rt.inc

xx MACRO args:VARARG
LOCAL tmp$
  tmp$ CATSTR <Myargs=>, <args>
  % echo tmp$
  for arg, <args>
echo arg
  endm
ENDM

.code
start:
  xx <1,2>, <2,3>
  xx <1:2>, <2:3>
  .err
end start

Echos:
Myargs=1,2,2,3
1
2
2
3
Myargs=1:2,2:3
1:2
2:3