News:

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

Main Menu

Using _beginthreadex

Started by TBRANSO1, January 11, 2019, 06:05:16 AM

Previous topic - Next topic

TBRANSO1

#30
It was rough and crude, and since I couldn't get it to assemble, I couldn't begin to debug it.

Here it is:

A few things that I don't like:
1. the randInt... in Nasm it seems I can use the rdtsc directive, but it flags an error in MASM: error A2085:instruction or register not accepted in current CPU mode, so it works well in Nasm on linux, but using GetTickCount, no so well.
2. I would like to implement it as a MACRO, like the rv example, where I have Map(parameters).
3. It appears that in Nasm I can input a mnemonic as a parameter into a macro, can anything be done like that in Masm?  for example... Map(mnemonic, map_operand, array, length)?


include /masm32/include/masm32rt.inc

map MACRO arg1, arg2, arg3, arg4:VARARG
FOR var, <arg4>
.if var == "m"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg3
L1:
mov edi, arg2
mov edx, DWORD PTR [edi+esi]
mov eax, arg3
mul edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L1
jmp _DONE
.elseif var == "a"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg3
L2:
mov edi, arg2
mov edx, DWORD PTR [edi+esi]
mov eax, arg1
add eax, edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L2
jmp _DONE
.elseif var == "s"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg3
L3:
mov edi, arg2
mov edx, DWORD PTR [edi+esi]
mov eax, arg1
sub eax, edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L3
jmp _DONE
.else
jmp _DONE
.endif
ENDM
_DONE:
;mov array, edi
;mov eax, array
    EXITM <eax>                           ;; EAX as the return value
ENDM

ExitProcess PROTO dwExitCode:DWORD
GetTickCount PROTO
Map PROTO operators:BYTE, operand:DWORD, array:PTR, ary_size:DWORD

public start

.CONST
    UPPER_NUM     EQU 10000

.DATA
    num_array DWORD 4 dup(0)
    array_len EQU LENGTHOF num_array
    mnemonic DB "m", 0
    whatever DB "msad", 0

.DATA?
    op DWORD ?

.CODE
start:
    call main

main PROC
    mov ecx, array_len
    mov esi, 0
  array_loop:
    push ecx
    push esi
    call randInt
    mov edi, eax
    print str$(edi), 13, 10
    pop esi
    mov DWORD PTR [num_array+esi], edi
    add esi, 4
    pop ecx
    loop array_loop
    mov op, 0FFh
    mov num_array, rv(Map, mnemonic, op, offset num_array, array_len)
    mov ecx, array_len
    mov edi, 0
display_loop:
    push ecx
    print str$([num_array+edi]), 13, 10
    add edi, 4
    pop ecx
    loop display_loop
    push 0
    call ExitProcess
main ENDP

randInt PROC
    push ebp
    mov ebp, esp
    xor edx, edx
    mov edx, UPPER_NUM
    mov esi, edx
    xor ecx, ecx
    mov eax, ecx
    cmp eax, edx
    jl in_order
    xchg eax, edx
    mov ecx, eax

in_order:
    call GetTickCount
    and eax, 0FFFh
    shr eax, 1
    mov ebx, esi
    add ebx, 1
    sub ebx, ecx
    cdq
    xor edx, edx
    idiv ebx
    add esi, ecx
    mov eax, edx
    mov esp, ebp
    pop ebp
    ret
randInt ENDP

Map PROC operator:BYTE, operand:DWORD, array:PTR, ary_size:DWORD
mov ebp, esp
sub esp, 10h
.if operator == "m"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, ary_size
L1:
mov edi, array
mov edx, DWORD PTR [edi+esi]
mov eax, operand
mul edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L1
jmp _DONE
.elseif [operator] == "a"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, ary_size
L2:
mov edi, array
mov edx, DWORD PTR [edi+esi]
mov eax, operand
add eax, edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L2
jmp _DONE
.elseif [operator] == "s"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, ary_size
L3:
mov edi, array
mov edx, DWORD PTR [edi+esi]
mov eax, operand
sub eax, edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L3
jmp _DONE
.else
jmp _DONE
.endif
_DONE:
;mov array, edi
;mov eax, array
add esp, 10h
mov esp, ebp
ret
Map ENDP
end start


EDIT/UPDATE:

Ok, I went through:
1. I have a better number generator using the rdtsc (as DedDave below notes), need to use the .686 directive
2. still outstanding issue
3. still outstanding issue


include /masm32/include/masm32rt.inc

ExitProcess PROTO :DWORD
GetTickCount PROTO
rand PROTO C :PTR
Map PROTO :BYTE, :DWORD, :PTR, :DWORD

map MACRO arg1, arg2, arg3, arg4:VARARG
FOR var, <arg4>
.if var == "m"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg3
L1:
mov edi, arg2
mov edx, DWORD PTR [edi+esi]
mov eax, arg3
mul edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L1
jmp _DONE
.elseif var == "a"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg3
L2:
mov edi, arg2
mov edx, DWORD PTR [edi+esi]
mov eax, arg1
add eax, edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L2
jmp _DONE
.elseif var == "s"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg3
L3:
mov edi, arg2
mov edx, DWORD PTR [edi+esi]
mov eax, arg1
sub eax, edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L3
jmp _DONE
.else
jmp _DONE
.endif
ENDM
_DONE:
;mov array, edi
;mov eax, array
    EXITM <eax>                           ;; EAX as the return value
ENDM

public start

.CONST
    UPPER_NUM EQU 10000
    STDOUT EQU -11

.DATA
    num_array DWORD 5 dup(0)
    array_len EQU LENGTHOF num_array
    mnemonic DB "m", 0
    whatever DB "msad", 0
    message1 DB "Pre-mapped array: ", 13, 10
message2 DB "Post-mapped array: ", 13, 10
    msg_len EQU LENGTHOF message1
msg_len2 EQU LENGTHOF message2
    newline DB 13, 10

.DATA?
    handle DWORD ?
    bytesWritten DWORD ?
    op DWORD ?

.CODE
start:
    call main

main PROC
    mov handle, rv(GetStdHandle, STDOUT)
    INVOKE WriteConsoleA, handle, addr message1, msg_len, addr bytesWritten, 0
    mov ecx, array_len
    mov esi, 0
  array_loop:
    push ecx
    push esi
    call randInt
    mov edi, eax
    print str$(edi), 32
    pop esi
    mov DWORD PTR [num_array+esi], edi
    add esi, 4
    pop ecx
    loop array_loop
    mov bytesWritten, 0
    INVOKE WriteConsoleA, handle, addr newline, 2, addr bytesWritten, 0
    mov op, 2d
    mov num_array, rv(Map, mnemonic, op, offset num_array, array_len)
    mov bytesWritten, 0
    INVOKE WriteConsoleA, handle, addr message2, msg_len2, addr bytesWritten, 0
    mov ecx, array_len
    mov edi, 0
display_loop:
    push ecx
    print str$([num_array+edi]), 32
    add edi, 4
    pop ecx
    loop display_loop
    mov bytesWritten, 0
    INVOKE WriteConsoleA, handle, addr newline, 2, addr bytesWritten, 0
    push 0
    call ExitProcess
main ENDP

randInt PROC
    push ebp
    mov ebp, esp
    xor edx, edx
    mov edx, UPPER_NUM
    mov esi, edx
    xor ecx, ecx
    mov eax, ecx
    cmp eax, edx
    jl in_order
    xchg eax, edx
    mov ecx, eax

in_order:
    rdtsc
    shr eax, 2
    mov ebx, esi
    add ebx, 1
    sub ebx, ecx
    cdq
    xor edx, edx
    idiv ebx
    add esi, ecx
    mov eax, edx
_EXIT:
    mov esp, ebp
    pop ebp
    ret
randInt ENDP

Map PROC operator:BYTE, operand:DWORD, array:PTR, ary_size:DWORD
mov ebp, esp
sub esp, 10h
.if operator == "m"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, ary_size
mov edi, array
L1:
mov edx, DWORD PTR [edi+esi]
mov eax, operand
mul edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L1
jmp _DONE
.elseif [operator] == "a"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, ary_size
L2:
mov edi, array
mov edx, DWORD PTR [edi+esi]
mov eax, operand
add eax, edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L2
jmp _DONE
.elseif [operator] == "s"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, ary_size
mov edi, array
L3:
mov edx, DWORD PTR [edi+esi]
mov eax, operand
sub edx, eax
xchg edx, eax
mov DWORD PTR [edi+esi], eax
add esi, TYPE DWORD
loop L3
jmp _DONE
.else
jmp _DONE
.endif
_DONE:
mov eax, DWORD PTR [edi]
add esp, 10h
mov esp, ebp
  ret
Map ENDP
end start

dedndave

if you use ".586" or ".686", you should be able to use RDTSC

.... or, you could hardcode it as
  DW 310Fh
or
  DB 0Fh,31h

jj2007

Here is a skeleton for the macro. Usage: mov eax, map("m", op, offset num_array, array_len)

map MACRO arg1, arg2, arg3, arg4
Local tmp$
  ifidn <arg1>, <"m">
; echos appear in the output window
echo Yeah, it's the "m"
mov esi, arg2
mov edi, arg3
mov ecx, arg4
; ... more code ...
  else
tmp$ CATSTR <Your first arg is >, <arg1>, < - whatever that means>
% echo tmp$
  endif
  exitm <eax>
ENDM

TBRANSO1

Quote from: dedndave on January 14, 2019, 11:53:21 AM
if you use ".586" or ".686", you should be able to use RDTSC

.... or, you could hardcode it as
  DW 310Fh
or
  DB 0Fh,31h

Great!!!

Since I am using the MASM32 include of masm32rt.inc, and it was coded with a .486... I changed it to .686, and I'll be hornswaggled!

Bless ya, my snail.  :lol:

I now have my original and better random number generator back.  :t

I EDITED the above post with the 2nd code block to reflect updates.

hutch--

Go the whole hog.

.686p
.mmx
.xmm

These size restrictions go back to the days when you could not run early Pentium code on an 8086. Turn everything on and you have escaped the old stuff.

Raistlin

QuoteTurn everything on and you have escaped the old stuff.
Yes, as initially suggested. Please add CPU detection to your code for production releases
to ensure run-time compatibility - if you use strange and wonderful instructions. On another
topic : macros. As pointed out by jj2007 and hutch the MASM32 library and macro calls typically
do not add significant cycles to your code [after-all the code is refactored to be extremely speedy
over years of use, by many many forum members and tireless hutch]
MASM = MacroASseMbler [it's in the name  :icon_eek:] macro's are just short hand notation for
code-lets. Thus produce the same processing cycles as the long-hand versions. They are convenient
and produce more readable/maintainable/consistent code.  But it's always a good idea to research
what exactly they do under the hood as to avoid register thrashing or unpredictable results.
Are you pondering what I'm pondering? It's time to take over the world ! - let's use ASSEMBLY...

TBRANSO1

#36
Okey dokey,

I am pretty much done with this assignment.

I am still working on the MACRO part.

This finally turned out decent.

TO: I was unsure about that rv macro, but that thing is cool, when I did the mov handle, rv(GetStdHandle, STDOUT), in there.

I have learned to embrace INVOKE for speed and brevity.

It took me a long time to figure out why the first index[0] was coming back with what I thought was garbage, but it was the pointer to the array... got that solved.

Thar she blows


.XCREF
.NoList
INCLUDE    \Masm32\Include\Masm32rt.inc
.686p
.MMX
.XMM
.List

HANDLE typedef DWORD

ExitProcess PROTO :DWORD
Map PROTO :BYTE, :DWORD, :PTR, :DWORD

map MACRO arg1, arg2, arg3, arg4:VARARG
FOR var, <arg4>
.if var == "m"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg3
L1:
mov edi, arg2
mov edx, DWORD PTR [edi+esi]
mov eax, arg3
mul edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L1
jmp _DONE
.elseif var == "a"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg3
L2:
mov edi, arg2
mov edx, DWORD PTR [edi+esi]
mov eax, arg1
add eax, edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L2
jmp _DONE
.elseif var == "s"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg3
L3:
mov edi, arg2
mov edx, DWORD PTR [edi+esi]
mov eax, arg1
sub eax, edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L3
jmp _DONE
.else
jmp _DONE
.endif
ENDM
_DONE:
;mov array, edi
;mov eax, array
    EXITM <eax>                           ;; EAX as the return value
ENDM

public start

.CONST
    UPPER_NUM EQU 10000
    STDOUT EQU -11

.DATA
    num_array DWORD 5 dup(0)
    array_len EQU LENGTHOF num_array
    mnemonic DB "m", 0
    whatever DB "msad", 0
    message1 DB "Pre-mapped array: ", 13, 10
    message2 DB "Post-mapped array: ", 13, 10
    msg_len EQU LENGTHOF message1
    msg_len2 EQU LENGTHOF message2
    newline DB 13, 10

.DATA?
    handle                HANDLE ?
    bytesWritten DWORD ?
    op DWORD ?

.CODE
start:
    call main

main PROC
    mov handle, rv(GetStdHandle, STDOUT)
    INVOKE WriteConsoleA, handle, addr message1, msg_len, addr bytesWritten, 0
    mov ecx, array_len
    mov esi, 0
array_loop:
    push ecx
    push esi
    call randInt
    mov edi, eax
    print str$(edi), 32
    pop esi
    mov DWORD PTR [num_array+esi], edi
    add esi, 4
    pop ecx
    loop array_loop
    mov bytesWritten, 0
    INVOKE WriteConsoleA, handle, addr newline, 2, addr bytesWritten, 0
    mov op, 0Ah
    mov num_array, rv(Map, mnemonic, op, offset num_array, array_len)
    mov bytesWritten, 0
    INVOKE WriteConsoleA, handle, addr message2, msg_len2, addr bytesWritten, 0
    mov ecx, array_len
    mov edi, 0
display_loop:
    push ecx
    print str$([num_array+edi]), 32
    add edi, 4
    pop ecx
    loop display_loop
    mov bytesWritten, 0
    INVOKE WriteConsoleA, handle, addr newline, 2, addr bytesWritten, 0
    push 0
    call ExitProcess
main ENDP

randInt PROC
    push ebp
    mov ebp, esp
    xor edx, edx
    mov edx, UPPER_NUM
    mov esi, edx
    xor ecx, ecx
    mov eax, ecx
    cmp eax, edx
    jl in_order
    xchg eax, edx
    mov ecx, eax

in_order:
    rdtsc
    shr eax, 2
    mov ebx, esi
    add ebx, 1
    sub ebx, ecx
    cdq
    xor edx, edx
    idiv ebx
    add esi, ecx
    mov eax, edx
_EXIT:
    mov esp, ebp
    pop ebp
    ret
randInt ENDP

Map PROC operator:BYTE, operand:DWORD, array:PTR, ary_size:DWORD
mov ebp, esp
sub esp, 10h
.if operator == "m"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, ary_size
mov edi, array
L1:
mov eax, operand
mul DWORD PTR [edi+esi]
mov [edi+esi], eax
add esi, TYPE DWORD
loop L1
jmp _DONE
.elseif operator == "a"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, ary_size
mov edi, array
L2:
mov eax, operand
add eax, DWORD PTR [edi+esi]
mov [edi+esi], eax
add esi, TYPE DWORD
loop L2
jmp _DONE
.elseif operator == "s"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, ary_size
mov edi, array
L3:
mov edx, DWORD PTR [edi+esi]
mov eax, operand
sub edx, eax
xchg edx, eax
mov DWORD PTR [edi+esi], eax
add esi, TYPE DWORD
loop L3
jmp _DONE
.elseif operator == "d"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, ary_size
mov edi, array
L4:
mov eax, DWORD PTR [edi+esi]
xor edx, edx
cdq
idiv operand
mov [edi+esi], eax
add esi, TYPE DWORD
loop L4
jmp _DONE
.endif
_DONE:
mov eax, DWORD PTR [edi]
add esp, 10h
mov esp, ebp
  ret
Map ENDP
end start


Well, all in all, this was a tough little assignment.  I learned a great deal.

I am going to work on making it prettier.

Thanks All

OUTPUT with multiply by 10:
Pre-mapped array:
2857 1164 5858 9389 227
Post-mapped array:
28570 11640 58580 93890 2270

OUTPUT with divide by 10:
Pre-mapped array:
2975 7228 644 9804 1872
Post-mapped array:
29 72 6 98 18

subtract and add work also

jj2007

It works fine but your map macro is not being used and not operational. See my reply#32 above, you may have missed it.

dedndave

Quote from: TBRANSO1 on January 14, 2019, 04:13:32 PM
Since I am using the MASM32 include of masm32rt.inc, and it was coded with a .486... I changed it to .686....

it's not a good idea to alter the library file that way
now, when you post code that has "INCLUDE \masm32\include\masm32rt.inc",
other programmers will not be compatible

the CPU selection directive may be reassigned without a "duplicate" error
instead, do it like this...

INCLUDE \masm32\include\masm32rt.inc
.586


i start writing programs by using a template program
it starts like this

        .XCREF
        .NoList
        INCLUDE    \Masm32\Include\Masm32rt.inc
        .686p
        .MMX
        .XMM
        .List


also, RDTSC is not the only instruction like this
the same applies to using the CPUID instruction

TBRANSO1

Quote from: jj2007 on January 14, 2019, 06:41:24 PM
It works fine but your map macro is not being used and not operational. See my reply#32 above, you may have missed it.

Yes, this MACRO is a work in progress, I will work on this part now.

Quote from: dedndave on January 14, 2019, 06:41:24 PM
i start writing programs by using a template program
it starts like this

Code: [Select]

        .XCREF
        .NoList
        INCLUDE    \Masm32\Include\Masm32rt.inc
        .686p
        .MMX
        .XMM
        .List


also, RDTSC is not the only instruction like this
the same applies to using the CPUID instruction

I made those updates above.

TBRANSO1

An update to the update:

I finished the map MACRO: works just like the map PROC:

now I can do either:
mov array, rv(map, <parameters>)

OR

mov array, map(<parameters>)

I like the latter due to it looking more like Ruby or Python...  :eusa_naughty:


map MACRO var:REQ, arg2, arg3, arg4
.if var == "m"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg4 ; len
mov edi, arg2 ; array
L1:
mov edx, DWORD PTR [edi+esi]
mov eax, arg3 ; operator
mul edx
mov [edi+esi], eax
add esi, TYPE DWORD
loop L1
jmp _DONE
.elseif var == "a"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg4
mov edi, arg2
L2:
mov eax, arg3
add eax, DWORD PTR [edi+esi]
mov [edi+esi], eax
add esi, TYPE DWORD
loop L2
jmp _DONE
.elseif var == "s"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg4
mov edi, arg2
L3:
mov edx, DWORD PTR [edi+esi]
mov eax, arg3
sub edx, eax
xchg edx, eax
mov DWORD PTR [edi+esi], eax
add esi, TYPE DWORD
loop L3
jmp _DONE
.elseif var == "d"
xor eax, eax
xor esi, esi
xor ecx, ecx
mov ecx, arg4
mov edi, arg2
L4:
mov eax, DWORD PTR [edi+esi]
xor edx, edx
cdq
idiv arg3 ; 3dcccccd
mov [edi+esi], eax
add esi, TYPE DWORD
loop L4
jmp _DONE
.endif
_DONE:
mov eax, DWORD PTR [edi]
    EXITM <eax>                          ;; EAX as the return value
ENDM


I have one more question:

Can we pass an actual mnemonic as a parameter in a macro?

It appears that it is possible in NASM.

i.e.
%macro map 4 (args count)
    // code here
   %1 eax, 4  // where mul, div, add, sub would replace the %1
   // rest of code
%endmacro

so a macro definition call would be like:

map(mul, <parameters>) in MASM

???

hutch--

This should answer your question.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    addmacro MACRO mnemonic, register, value
      mnemonic register, value
    ENDM

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    xor eax, eax                ; mnemonic

    addmacro add, eax, 1234     ; macro

    print str$(eax),13,10       ; display result

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start


Here is a simplified version.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    addmacro MACRO register, value
      add register, value
    ENDM

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    xor eax, eax                ; mnemonic
    addmacro eax, 1234          ; macro
    print str$(eax),13,10       ; display result

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start


TBRANSO1

Quote from: hutch-- on January 19, 2019, 03:11:53 PM
This should answer your question.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    addmacro MACRO mnemonic, register, value
      mnemonic register, value
    ENDM

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    xor eax, eax                ; mnemonic

    addmacro add, eax, 1234     ; macro

    print str$(eax),13,10       ; display result

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start


Yep  :t

I have to refactor the macro now, as I try to differentiate between the different mnemonics instead of char literals.

@Hutch

I've been poking around the Masm32 includes and macros, reading help and MSDN docs... then using Select-String codelet in Powershell to find if the function or macro is available in MASM32.  I think that it has a 99% positive hit count, anything that didn't hit, I am adding.  Usually it's just small macros or defines... for example, I added the UNREFERENCED_PARAMETER macro, MSDN uses it a lot, not really neccessary, but it's an elegant way to stop the assembly warnings of unused parameter variable.

UNREFERENCED_PARAMETER MACRO param:REQ
   mov param, 0
ENDM


UNREFERENCED_PARAMETER(lpParam)


Anyways
Thanks

hutch--

I am not sure how you are using this macro but you can use :VARARG in macros if a variable argument count is required.

TBRANSO1

Quote from: hutch-- on January 20, 2019, 07:52:26 AM
I am not sure how you are using this macro but you can use :VARARG in macros if a variable argument count is required.

I find the Visual C++ unreferenced_parameter macro in a lot of MSDN examples.

BTW, I am curious to what the REQ means?  I see it a lot, and it seems to be used as a delimiter for the ( ) brackets?  But it's not in the MASM >= 14.0 docs, and I haven't found any full explanation for it yet.