Hi,
I figured out why the Hutch macros dont work :biggrin: :P Uasm doesn't understand the dot in the macro names, since we are committed to compatibility, I would like to suggest the introduction of a dot symbol definition in macros on UASM, just because the macro assembler supports this feature ;) :icon_exclaim: What do you think about this?
Examples of macros that UASM does not understand
.switch MACRO arg
;; ---------------------------------
;; checks the size and type of "arg"
;; ---------------------------------
IF getattr(arg) eq LAB or getattr(arg) eq IMM
% echo **************************************
% echo Only a memory operand or a register is
% echo allowed as the source in .switch macro
% echo **************************************
.err <parameter error>
goto byebye
ELSEIF getattr(arg) eq LOC or getattr(arg) eq GLO
goto isvar
ELSEIF getattr(arg) eq REG
goto isreg
ENDIF
:isvar
IF varsize(arg) eq 8
.switch_macro arg,rax
ELSEIF varsize(arg) eq 4
.switch_macro arg,eax
ELSEIF varsize(arg) eq 2
.switch_macro arg,ax
ELSE
% echo Unknown arg
.err
ENDIF
goto byebye
:isreg
IF regsize(arg) eq 8
.switch_macro arg,rax
ELSEIF regsize(arg) eq 4
.switch_macro arg,eax
ELSEIF regsize(arg) eq 2
.switch_macro arg,ax
ELSE
% echo Unknown arg
.err
ENDIF
:byebye
ENDM
; ====================================================
.switch_macro MACRO _var:req, _reg:=<rax>
mov _reg, _var
$casstk CATSTR <_reg>, <#>, $casflg, <#>, $casstk
$casvar equ _reg
$casflg equ <0> ;; 0 = emit an .if, 1 an .elseif
ENDM
; ====================================================
.case MACRO _args:vararg ;; like Pascal: case id1. id4 .. id8, lparam, ...
;; does an or (case1 || case2 || case3...)
$cas textequ <>
FOR $v, <_args> ;; for each case
t@ INSTR <$v>, <..> ;; range ?
IF t@ ;; yes
$LB SUBSTR <$v>, 1, t@-1 ;; lbound = left portion
$LB CATSTR <(>, $casvar, <!>=>, $LB, <)> ;; ($casvar >= lbound)
$UB SUBSTR <$v>, t@+2 ;; ubound = right portion
$UB CATSTR <(>, $casvar, <!<=>, $UB, <)> ;; ($casvar <= ubound)
$t CATSTR <(>, $LB, <&&> , $UB,<)> ;; (($casvar >= $lb) && ($casvar <= $ub))
ELSE ;; no, it's a value (var/const)
$t CATSTR <(>, $casvar, <==>, <$v>, <)> ;; ($casvar == value)
ENDIF
$cas CATSTR <|| >, $t, $cas ;; or this case w/ others
ENDM
$cas SUBSTR $cas, 3 ;; lose the extra "|| " in front
IFIDN $casflg, <0> ;; 0 = 1'st case
% .if $cas ;; emit ".if"
ELSE ;; all others
% .elseif $cas ;; emit ".elseif"
ENDIF
$casflg equ <1> ;; NOT 1'st
ENDM
; ====================================================
.default MACRO _default:vararg
.else
_default
ENDM
; ====================================================
.endsw MACRO _cmd:vararg
IFIDN $casstk, <>
.err <endsw w/o switch>
ELSE
t@ INSTR $casstk, <#>
$casvar SUBSTR $casstk, 1, t@-1
$casstk SUBSTR $casstk, t@+1
t@ INSTR $casstk, <#>
$casflg SUBSTR $casstk, 1, t@-1
IFIDN $casstk, <#>
$casstk equ <>
ELSE
$casstk SUBSTR $casstk, t@+1
ENDIF
.endif
endif
ENDM
; ||||||||||||||||||||||||||||||||||||||||||||||||||||||
.do MACRO
do_macro
ENDM
.loop MACRO args
bottom_evaluate args
ENDM
; ||||||||||||||||||||||||||||||||||||||||||||||||||||||
;; invoke MACRO fname:REQ,args:VARARG
;; procedure_call fname,args
;; ENDM
; -------------------------------
; ||||||||||||||||||||||||||||||||||||||||||||||||||||||
.rept MACRO args
top_evaluate args
ENDM
.endr MACRO
te_end
ENDM
; ||||||||||||||||||||||||||||||||||||||||||||||||||||||
; -------------------------------------------------------------------------
; *************************************************************************
.return MACRO arg
IF arg ne 0
mov rax, arg
ret
ELSE
xor rax, rax
ret
ENDIF
ENDM
.multiple_instruction MACRO delm:REQ,args:VARARG
LOCAL arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg0
LOCAL argA,agrB,argC,argD,argE,argF,cntr,flag
cntr = 1 ;; counter determined which buffer is being written to
flag = 0 ;; flag starts as clear
arg1 equ <>
arg2 equ <>
arg3 equ <>
arg4 equ <>
arg5 equ <>
arg6 equ <>
arg7 equ <>
arg8 equ <>
arg9 equ <>
arg0 equ <>
argA equ <>
argB equ <>
argC equ <>
argD equ <>
argE equ <>
argF equ <>
;; ---------------------------------
FORC char,<args>
IFIDN <char>,<delm> ;; test if char is the delimiter
IF flag eq 0
cntr = cntr + 1 ;; only increment the counter if the flag is clear
ENDIF
flag = 1 ;; set the flag so you only get 1 increment of cntr
goto over
ENDIF
flag = 0 ;; clear the flag when the next char is not a space
IF cntr eq 1
arg1 CATSTR arg1,<char> ;;
ELSEIF cntr eq 2
arg2 CATSTR arg2,<char> ;;
ELSEIF cntr eq 3
arg3 CATSTR arg3,<char> ;;
ELSEIF cntr eq 4
arg4 CATSTR arg4,<char> ;;
ELSEIF cntr eq 5
arg5 CATSTR arg5,<char> ;;
ELSEIF cntr eq 6
arg6 CATSTR arg6,<char> ;;
ELSEIF cntr eq 7
arg7 CATSTR arg7,<char> ;;
ELSEIF cntr eq 8
arg8 CATSTR arg8,<char> ;;
ELSEIF cntr eq 9
arg9 CATSTR arg9,<char> ;;
ELSEIF cntr eq 10
arg0 CATSTR arg0,<char> ;;
ELSEIF cntr eq 11
argA CATSTR argA,<char> ;;
ELSEIF cntr eq 12
argB CATSTR argB,<char> ;;
ELSEIF cntr eq 13
argC CATSTR argC,<char> ;;
ELSEIF cntr eq 14
argD CATSTR argD,<char> ;;
ELSEIF cntr eq 15
argE CATSTR argE,<char> ;;
ELSEIF cntr eq 16
argF CATSTR argF,<char> ;;
ELSEIF cntr eq 17
% echo *********************************************
% echo ERROR : too many arguments, 16 argument limit
% echo *********************************************
.err < <<< too many arguments >>> >
goto over
ENDIF
:over
ENDM
;; ---------------------------------
arg1
arg2
arg3
arg4
arg5
arg6
arg7
arg8
arg9
arg0
argA
argB
argC
argD
argE
argF
ENDM
; --------------------------------
.mi MACRO args:VARARG ;; multiple instructions
.multiple_instruction :,args
ENDM
.ma MACRO args:VARARG ;; multiple arguments
.multiple_instruction #,args
ENDM
.mn MACRO args:VARARG ;; alternate multiple arguments
.multiple_instruction &,args
ENDM
.mx MACRO args:VARARG ;; alternate multiple arguments
.multiple_instruction ^,args
ENDM
;; --------------------------------
;; These delimiters also work * $ |
;; --------------------------------
; -------------------------------------------------------------------------
; *************************************************************************
.exit MACRO optvar:=<0>
invoke ExitProcess,optvar
ENDM
ERROR: The process "mspdbsrv.exe" not found.
Translated Windows SDK 10 64 bits
windef WIN_INTERNAL manque ENDIF
macros64_Uasm.inc(2413) : Error A2222: Doesn't work with 32-bit segments: .exit
macros64_Uasm.inc(2413): Included by
mywindow1.asm(32): Main line code
macros64_Uasm.inc(2415) : Error A2163: Unmatched macro nesting
macros64_Uasm.inc(2415): Included by
mywindow1.asm(32): Main line code
mywindow1.asm: 97 lines, 1 passes, 186 ms, 0 warnings, 2 errors
Microsoft (R) Incremental Linker Version 14.14.26433.3
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1181: cannot open input file 'mywindow1.obj'
ERROR: The process "mspdbsrv.exe" not found.
Press any key to continue . . .
See if UASM supports OPTION DOTNAME
include \masm32\include\masm32rt.inc
option dotname
.yes macro
inkey "it does, of course"
endm
.code
start:
.yes
exit
end start
However, that won't help much, as discussed here (http://masm32.com/board/index.php?topic=6447.msg69120#msg69120): "it is possible to use both Microsoft ML64 (requiring .if eax}=edx) and UAsm (happy with .if eax>=edx) with identical sources and include files". Scroll down for "occasional switch" 8)
Hi Hutch, Jochen,
UASM does not support "option dotname", I just checked it.
QuoteHowever, that won't help much, as discussed here: "it is possible to use both Microsoft ML64 (requiring .if eax}=edx) and UAsm (happy with .if eax>=edx) with identical sources and include files". Scroll down for "occasional switch" 8)
In this case it would help, I have compiled all the macros, except those listed above. Hutch did not use such constructs in his macro set, I'm not talking about other macros, such as .if eax}=edx, we will have to correct this entry manually, and the dot works by default in macro assembler. Then, I can write any other similar macro with a dot without the parentheses type definitions, this is another level of compliance, at the code level, and not at the macro level. As I wrote in the first post
Quote"just because the macro assembler supports this feature"
. The final goal is not willing to support the macros of Vasiliy ::) I hope that I clearly explained my thoughts :biggrin: :P :redface:
Quote from: LiaoMi on August 30, 2018, 05:57:13 PMUASM does not support "option dotname", I just checked it.
Check once more. I test my code before posting it...
Once again, my test 8) Assemble with the latest version of uasm64 :eusa_boohoo:
.686
.MMX
.XMM
.x64
option casemap:none
option win64:11
option frame:auto
option stackbase:rsp
option dotname
;option proc:private
WIN32_LEAN_AND_MEAN equ 1
.nolist
.nocref
ERROR: The process "mspdbsrv.exe" not found.
Translated Windows SDK 10 64 bits
windef WIN_INTERNAL manque ENDIF
macros64_Uasm.inc(2413) : Error A2222: Doesn't work with 32-bit segments: .exit
macros64_Uasm.inc(2413): Included by
mywindow1.asm(33): Main line code
macros64_Uasm.inc(2415) : Error A2163: Unmatched macro nesting
macros64_Uasm.inc(2415): Included by
mywindow1.asm(33): Main line code
mywindow1.asm: 98 lines, 1 passes, 137 ms, 0 warnings, 2 errors
Microsoft (R) Incremental Linker Version 14.14.26433.3
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1181: cannot open input file 'mywindow1.obj'
ERROR: The process "mspdbsrv.exe" not found.
Press any key to continue . . .
I'm testing on a simple macro
.exit MACRO optvar:=<0>
invoke ExitProcess,optvar
ENDM
:biggrin:
There is an old expression in English that fits the bill here, "People in glass houses should not throw stones".
> "it is possible to use both Microsoft ML64 (requiring .if eax}=edx)
Look at this tangled mess in MasmBasic.
For_ ct=0 To MyInts(?)-1
test MyInts(ct), 1
setne al
movsx ecx, al
Print #ecx, Str$("%__i ", MyInts(ct))
You appear to be confused with the distinction between win32 and win64, ML64 does not assembler 32 bit code.
In MASM 32 bit you would use,
.if eax >= edx
This inherently is the problem of relying on legacy knowledge of 32 bit instead of writing true 64 bit, cat scratching about notation that you simply don't understand.
Quote from: LiaoMi on August 30, 2018, 06:51:28 PM
I'm testing on a simple macro
.exit MACRO optvar:=<0>
invoke ExitProcess,optvar
ENDM
You have a collition, because a lot of "dots-something" are new UAsm directives. You can disable that rebuildind UAsm after change directives names. In contrast Asmc allow you to disable all new directives using options for that (then AsmC work almost exactly like Masm)
I think you would have to ask John to add the MASM format DOT prefix as it is very useful in doubling the naming range. This has been reliable in MASM since before the 1990 MASM 6.0 so if the Watcom forks are supposed to be MASM compatible, they should be able to do this.
mov ; intel mnemonic
.mov ; macro
Many others as well.
.if
.If
.IF
; any form of IF in MASM is a conditional assembly directive.
Quote from: HSE on August 30, 2018, 10:36:52 PM
Quote from: LiaoMi on August 30, 2018, 06:51:28 PM
I'm testing on a simple macro
.exit MACRO optvar:=<0>
invoke ExitProcess,optvar
ENDM
You have a collition, because a lot of "dots-something" are new UAsm directives. You can disable that rebuildind UAsm after change directives names. In contrast Asmc allow you to disable all new directives using options for that (then AsmC work almost exactly like Masm)
Hi HSE,
:t :eusa_dance: Absolutely right! That's exactly what I needed, I just renamed the name of the macro after the dot symbol and it works! The description of the error "Error A2222: Doesn't work with 32-bit segments: .exit" led me to doubt. excellent!
The simplest approach is to write your own macros, although the Watcom forks claim to be MASM compatible, if they add capacity that differs the compatibility is lost.
I run into the same problem with a compiler that I use for some types of string work, so many common names are taken by the compiler so you have to keep finding other names.
.exit MACRO optvar:=<0>
invoke ExitProcess,optvar
ENDM
This is possible in ML64 because it is an unconfigured assembler so you can create your own dot prefix named macros without any problems. When the assembler uses that naming range with reserve words you have to find a new naming convention and there should be many that you can use.
@exit MACRO etc ....
.exit? MACRO etc ....
exit? MACRO etc ....
The general drift is to use a method that is consistent across the range of macros so they are easily recognised.
Quote from: hutch-- on August 30, 2018, 10:17:23 PM
"People in glass houses should not throw stones".
Great expression! :biggrin:
Quote@exit MACRO etc ....
.exit? MACRO etc ....
exit? MACRO etc ....
This macro definition looks beautiful :P Microsoft in the past used a similar style, so we will be like the old fashion programmers :t
:biggrin:
Here is the real McCoy, three original macro files from MASM 6.00 in 1990. I had to load them with the PWB editor and save them as text files. I still have this ancient stuff on a PIV that has XP on it. It cames out of a PIII archive I saved long ago.
LiaoMi,
Give something like this a blast.
.quit MACRO optvar:=<0>
invoke ExitProcess,optvar
ENDM
The trick is to get a list of the reserve words in UASM so you don't try and duplicate them then look for expressions that represent what you want to do with the macro. Terminating an application is an easy one as you can use any number of names. If UASM supports the dot prefix which I gather it does, you can use it when you are doing control flow things or low level items that are not covered by the UASM assembler.
You don't need macros for ".if", ".switch" and similar as I gather they are provided by UASM and there is some wisdom in not using dot prefixes for normal code components as they lose their easy readability if you use too many of them.
IMHO the message Error A2222: Doesn't work with 32-bit segments: .exit indicates that this is a relic from 16-bit times; and indeed, 16-bit code containing .exit assembles just fine. With ML and UAsm btw, their behaviour is identical.
Then use it without the dot prefix.
; --------------------------------------------------------
; exit macro with an optional return value for ExitProcess
; --------------------------------------------------------
exit MACRO optional_return_value
IFNDEF optional_return_value
invoke ExitProcess, 0
ELSE
invoke ExitProcess,optional_return_value
ENDIF
ENDM
Right. Shorter version:
exit MACRO optretval:=<0>
invoke ExitProcess, optretval
ENDM
...
exit
exit 123
Under the hood, e.g. as 64-bit code (assembled with ML64):
0000000140001A15 | 33 C9 | xor ecx,ecx |
0000000140001A17 | FF 15 EB 05 00 00 | call qword ptr ds:[<&RtlExitUserProcess>] |
0000000140001A1D | B9 7B 00 00 00 | mov ecx,7B | 7B:'{'
0000000140001A22 | FF 15 E0 05 00 00 | call qword ptr ds:[<&RtlExitUserProcess>] |
That's the one from the macro help file for 32 bit MASM written before 2000. This is the 21st century MASM version which should build in UASM without the dot prefix.
.exit MACRO optvar:=<0>
invoke ExitProcess,optvar
ENDM