So it's that time again.. a new release, lots of new goodness coming to a store near you ;)
What have we got in this release?
Fixed:
-----------------------------
1) Corrected some misplaced samples in the packages.
2) Fix incorrect detection of used proc parameter vs. global struct member.
3) Promote immediate vararg arguments to qword when too large for signed dword.
Improvements:
-----------------------------
1) Add signed 1 byte displacement optimisation to all vex and evex encoded memory operands.
2) I've combined the various manual/documents into a single manual now.
3) Support return types and vectorcall in OO interfaces and updated OO samples.
4) Added return type support to OO interfaces.
5) Add .endf and .endsw aliases for .endfor and .endswitch
And the big new features:
-----------------------------
1) Added C-style function calling.
The following is now possible:
.if ( MyProc6( MyProc8() ) == 7 )
xor eax,eax
.endif
mov eax,MyProc(10, 20)
lea rsi,myVar
mov eax,[rsi + MyProc12()]
mov myVar,MyProc(11,12)
mov myVar2,MyProc12()
vmovaps xmm1,MyProc5(1.0)
MyProc3()
MyProc(10,20)
MyProc(10,ADDR MyProc)
MyProc2("this is a literal")
.if( MyProc(10,20) == 30 )
xor eax,eax
.endif
.if( MyProc5(1.0) == FP4(2.0) )
xor eax,eax
.endif
.if ( MyProc6(7) == 7 )
xor eax,eax
.endif
MyProc(MyProc3(), 20)
MyProc(10, MyProc4())
MyProc(MyProc3(), MyProc4())
MyProc(MyProc3(), MyProc2("stringy"))
MyProc10(MyProc11(), MyProc2("stringy"))
MyProc7( 10, 20, myVar, myVar2, 2.0, 30 )
MyProc( MyProc( MyProc3(), 10 ), 20)
.if ( MyProc6( MyProc8() ) == 7 )
xor eax,eax
.endif
MyProc7( 10, 20, myVar, myVar2, MyProc9( 10, 20, myVar, myVar2, 2.0, 30 ), 30 )
MyProc7( 10,
20,
myVar,
myVar2,
2.0,
30 )
All the HL/C style calls are implemented under the hood via macros, and only a light shim in the pre-processor is required which means these features do not impact or cause any other issues with existing parser or expression evaluator logic and can rely on the already powerful macro expansion system to deal with the recursions etc. Internally the macros also respect the architecture selection (AVX vs SSE) and the ordinal of the argument, so that return values are correctly loaded into the corresponding register or stack locations.
Procedure calls can be nested 1 level deep, inner calls preserver the registers of the outer call parameters where required, and all support return typing and can be used in other HLL expressions, which can be especially fun when combined with the HLL floating point comparison operators.
2) Support pointer syntax with -> and allow c-style calls via pointer and OO methods.
The above higher level calling features have been further extended with support for a c-style pointer operator ( -> ) which can then be applied to the object oriented framework:
; Method invocation using c-style calls.
albl: person1->Calc(1.0)
person2->Calc(2.0)
.if( person1->Calc(1.0) == FP4(2.0) )
xor eax,eax
.endif
; Using a register as an object pointer with c-style calls requires the type to specified after the pointer.
; The register must be doubley-indirect, in that it points to the pointer to the object, which allows for rapid iteration through lists of object pointers.
lea rsi,person1
[rsi].Person->Calc(1.0)
.if( [rsi].Person->Calc(1.0) == FP4(2.0) )
xor eax,eax
.endif
xor rax,rax
lea rsi,person2
[rsi+rax].Person->Calc(1.0)
xor rax,rax
.if( [rsi+rax].Person->Calc(1.0) == FP4(2.0) )
xor eax,eax
.endif
person1->Calc( person2->Calc(1.0) ) ; Pass the typed result of a method call to another method.
NormalProc( person1->Calc(1.0) ) ; Pass the typed result of a method call to a normal procedure.
person1->Calc( NormalProc(1.0) ) ; Pass the typed result of a normal procedure to a method call.
person2->DoAdd( 1.0, NormalProc(2.0) )
; Delete the objects.
_DELETE(person1)
_DELETE(person2)
3) Add COMINTERFACE support built-in to allow direct implementation and use of COM objects without all the boilerplate wrapper nonsense.
Building on the previous two features, direct declaration of COM object interfaces and their invocation is now a doddle:
; Declare a COM interface for IDirect3D9
COMINTERFACE IDirect3D9
CVIRTUAL RegisterSoftwareDevice, DWORD, :PTR
CVIRTUAL GetAdapterCount, DWORD
CVIRTUAL GetAdapterIdentifier, DWORD
CVIRTUAL GetAdapterModeCount, DWORD
CVIRTUAL EnumAdapterModes, DWORD
CVIRTUAL GetAdapterDisplayMode, DWORD
CVIRTUAL CheckDeviceType, DWORD
CVIRTUAL CheckDeviceFormat, DWORD
CVIRTUAL CheckDeviceMultiSampleType, DWORD
CVIRTUAL CheckDepthStencilMatch, DWORD
CVIRTUAL CheckDeviceFormatConversion, DWORD
CVIRTUAL GetDeviceCaps, DWORD, Adapter:DWORD, DeviceType:DWORD, pCaps:PTR
CVIRTUAL GetAdapterMonitor, DWORD
CVIRTUAL CreateDevice, DWORD
ENDCOMINTERFACE
LPDIRECT3D9 TYPEDEF PTR IDirect3D9
; Call it :)
mov direct3d,Direct3DCreate9( D3D_SDK_VERSION )
.if( rax != 0 )
direct3d->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, ADDR caps )
.endif
4) And possibly the most important, I've finally gotten around to updating and merging all the regression testing sets from nasm, gas, jwasm, uasm and asmc and implementing a fully automated set of testing on each build. All the results from these tests have been fixed in 2.46 so there should be a lot fewer (hopefully no) regressions or encoding issues going forward from here. The tests are included in the regress folder in the github repository and also include the OO features, macrolib, Linux64, SystemV and various other UASM only features. This brought up a few encoding issues in AVX2 and AVX512 which are now fixed.
5) Thanks to AW27's work on SEH we've ensured that both the manual and automated models that he has developed work in UASM. These are included as part of the regression tests.
Planning for 2.47 is underway, first features to be picked up are support for DWARF debugging output, some new Linux and OSX GTK+ samples and merging in the last bunch of regression tests.
Cheers
John
Packages will be available this evening for all platforms.
wow amazing work. Thanks for all your hard work to all involved with the uasm developments.
Thanks your efforts. :t :t :t
we'll await the UASM 2.46 Release.
the UASM made max-win32asm compatible with its styles.
COMINTERFACE support is something beyond my expecrtations .
However I don't see IUnknown interface functions in IDirect3D9 declaration?
Hi habran and johnsa,
Many thanks for your amazing efforts :t
Quote from: GoneFishing on December 05, 2017, 05:40:36 AM
COMINTERFACE support is something beyond my expecrtations .
However I don't see IUnknown interface functions in IDirect3D9 declaration?
Correct, the iunknown members are automatically included as part of the COMINTERFACE definition as they're mandatory, so no point having to re-write them all the time.
Sounds great :t
Packages are up. :)
John
MasmBasic library:
UASM v2.46, Dec 4 2017, Masm-compatible assembler.
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.
*** MasmBasic version 30.11.2017 ***
Tmp_File.asm: 787 lines, 4 passes, 406 ms, 0 warnings, 0 errors
*** Link MasmBasic.obj using link, sub Console - no resources ***
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Tmp_file.obj : error : Internal error during ReadSymbolTable
ExceptionCode = C0000005
ExceptionFlags = 00000000
ExceptionAddress = 00432EEB
NumberParameters = 00000002
ExceptionInformation[ 0] = 00000000
ExceptionInformation[ 1] = 1CA5E519
CONTEXT:
Eax = 0FCDA2C8 Esp = 0018F654
Ebx = 00000000 Ebp = 003072F9
Ecx = 00000002 Esi = 00302E74
Edx = 8E3AB908 Edi = 65AF2871
Eip = 00432EEB EFlags = 00010246
SegCs = 00000023 SegDs = 0000002B
SegSs = 0000002B SegEs = 0000002B
SegFs = 00000053 SegGs = 0000002B
Dr0 = 0018F654 Dr3 = 00000000
Dr1 = 003072F9 Dr6 = 00000002
Dr2 = 00000000 Dr7 = 00000000
*** build all took 3356 ms ***
RichMasm triggers an exception in polink:
0040FFCF ³. C745 EC 00000000 mov dword ptr [ebp-14], 0
0040FFD6 ³> 8B45 F0 mov eax, [ebp-10]
0040FFD9 ³. 6B40 04 12 imul eax, [eax+4], 12
0040FFDD ³. 89C6 mov esi, eax
0040FFDF ³. 0335 C0214200 add esi, [4221C0] ; ASCII ".file"
0040FFE5 ³. 807E 10 02 cmp byte ptr [esi+10], 2 ; <<<<<<<<<<< esi is EA534DD7
0040FFE9 ³. 74 06 je short 0040FFF1
0040FFEB ³. 807E 10 69 cmp byte ptr [esi+10], 69
0040FFEF ³. 75 12 jne short 00410003
0040FFF1 ³> 89F1 mov ecx, esi
0040FFF3 ³. E8 F80A0000 call 00410AF0
0040FFF8 ³. 89C1 mov ecx, eax
0040FFFA ³. E8 5172FFFF call 00407250 ; [polink.00407250
RichMasm with the Masm32 SDK linker:*** Link ReTest.obj rsrc.obj using link, sub Windows ***
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Tmp_file.obj : error : Internal error during ReadSymbolTable
ExceptionCode = C0000005
ExceptionFlags = 00000000
ExceptionAddress = 00432EEB
NumberParameters = 00000002
ExceptionInformation[ 0] = 00000000
ExceptionInformation[ 1] = EAA34DE7
CONTEXT:
Eax = 1B3D4C90 Esp = 0018F654
Ebx = 00000000 Ebp = 0053EBB7
Ecx = 00000002 Esi = 00531440
Edx = F527B110 Edi = 65AF2871
Eip = 00432EEB EFlags = 00010246
SegCs = 00000023 SegDs = 0000002B
SegSs = 0000002B SegEs = 0000002B
SegFs = 00000053 SegGs = 0000002B
Dr0 = 0018F654 Dr3 = 00000000
Dr1 = 0053EBB7 Dr6 = 00000002
Dr2 = 00000000 Dr7 = 00000000
Well that is really odd.. I assume it works fine with 2.45? If so, can you send me both obj files (2.46 assembled and 2.45 so I can diff the obj files to see what is up).
Thanks! :) John
Here they are for the editor :icon14:
Hi jj, :biggrin:
I think your problem is related to some external vars:
extern _xzmb: byte
extern _MbExeFolder$: dword
extern _wfd: dword
extern _CrLf$: dword
?_1846: mov edx, dword ptr [_MbExeFolder$] ; 0000E85F _ 8B. 15, 00000000(d)
?_1846: mov edx, dword ptr [Unnamed_80000000_0] ; 0000E85F _ 8B. 15, 00000000(d)
push dword ptr [_CrLf$] ; 0000FEE7 _ FF. 35, 00000000(d)
push dword ptr [Unnamed_80000000_0] ; 0000FEE7 _ FF. 35, 00000000(d)
As you can see they are missing for the linker
Are you sure you included a proper include files
I have compared those 2 files you've posted and only problem is those externs
Quote from: habran on December 05, 2017, 11:32:08 AMAre you sure you included a proper include files
Yes, I am sure.
It is interesting that these vars are missing, have look here:
extern _DllTable: dword extern _DllTable: dword
extern _MbFH: dword extern _MbFH: dword
extern _MbExeFolder$: dword
extern _Dw2BinBuffer: byte extern _Dw2BinBuffer: byte
extern _wfd: dword
extern _MbCat$: dword extern _MbCat$: dword
extern _hSetWin: dword extern _hSetWin: dword
extern _CrLf$: dword
extern _Lf$: dword extern _Lf$: dword
jj, can you try assemble it using -nomlib command line option ?
Quote from: johnsa on December 05, 2017, 08:33:19 PM
jj, can you try assemble it using -nomlib command line option ?
No effect, linker chokes at exactly the same location as before. Sorry... :icon14:
Hmm.. ok I was thinking perhaps the pre-processor additions were swallowing those lines for some reason, as nothing has been touched in extern/coff/obj output at all to warrant this sudden issue.
How do you declare the extern ? Maybe there is something else specific about the line
Quote from: johnsa on December 05, 2017, 09:52:42 PMHow do you declare the extern ? Maybe there is something else specific about the line
Quote from: habran on December 05, 2017, 08:16:28 PM
It is interesting that these vars are missing, have look here:
extern _DllTable: dword extern _DllTable: dword
extern _MbFH: dword extern _MbFH: dword
extern _MbExeFolder$: dword
extern _Dw2BinBuffer: byte extern _Dw2BinBuffer: byte
extern _wfd: dword
extern _MbCat$: dword extern _MbCat$: dword
extern _hSetWin: dword extern _hSetWin: dword
extern _CrLf$: dword
extern _Lf$: dword extern _Lf$: dword
It's all in MasmBasic.inc:
ExternDef MbExeFolder$:DWORD
ExternDef MbFH:DWORD
ExternDef DllTable:DWORD
ExternDef MbCat$:DWORD
ExternDef wfd:WIN32_FIND_DATAW
ExternDef hSetWin:DWORD
ExternDef Cr$:DWORD
ExternDef Lf$:DWORD
ExternDef CrLf$:DWORD
ExternDef Dw2BinBuffer:DWORD
etc...
align 4 ; end of MbDATA
.data ; common initialised data
align 4
CrLf$ dd CrLf_txt ; pointer to 0D0A
Cr$ dd Cr_txt ; chr(13)
Lf$ dd Lf_txt ; chr(10)
Tb$ dd Tab_txt ; chr(9)
MbExeFolder$ dd MbExFoBuf
MbDefNum dd 7 ; f2sPrec
MbError$ dd mcErrBuf
Nothing unusual; and it works with ML, UAsm 2.45 and earlier, AsmC, linkv615, linkv9, polink...
Hi habran and johnsa
Testing the example below, I get the following error message :
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\msvcrt.lib
printf PROTO C :DWORD,:VARARG
sum PROTO :DWORD,:DWORD
.data
str1 db '%u',0
.code
start:
sum(90,sum(20,10))
printf( ADDR str1,sum( 80,20 ) )
invoke ExitProcess,0
sum PROC x:DWORD,y:DWORD
mov eax,x
add eax,y
ret
sum ENDP
END start
UASM v2.46, Dec 4 2017, Masm-compatible assembler.
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.
***********
ASCII build
***********
Test.asm(24) : Error A2178: Too many arguments to INVOKE
Test.asm(25) : Error A2228: Missing right parenthesis in expression
Test.asm(25) : Error A2102: Symbol not defined : arginvoke
Test.asm(25) : Error A2210: Syntax error: )
Test.asm: 36 lines, 1 passes, 264 ms, 0 warnings, 4 errors
Mea culpa.. I completely forgot to add 32bit version ... :icon_redface:
I'm adding in the 32bit macros now and have added in additional tests to the automated tests for these, will have that ready tomorrow :)
I also have an idea what might be causing the issue for JJ, it's not confirmed it's only a suspicion, fingers crossed though.
x86/x64 packages updated with the fix for the issue JJ was experiencing.
Vortex, I've added the 32bit macros in now so your example works, it's also included as a regression test-case now and I've taken it one step further with a 2nd test case as follows:
.686p
.mmx
.xmm
.model flat,stdcall
option casemap:none
option literals:on
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\msvcrt.lib
printf PROTO C :PTR, :VARARG
sum PROTO :DWORD, :DWORD
sumAsFlt PROTO REAL4 :DWORD, :DWORD
.data
str1 db '%u',13,10,0
str2 db '%f',13,10,0
.code
start:
sum( 90, sum( 20, 10 ) )
printf( ADDR str1, sum( 80, 20 ) )
printf( ADDR str2, 1.0 )
printf( "%f\n", sumAsFlt( 20, 30 ) )
invoke ExitProcess,0
sum PROC x:DWORD, y:DWORD
mov eax,x
add eax,y
ret
sum ENDP
sumAsFlt PROC REAL4 x:DWORD, y:DWORD
mov eax,x
add eax,y
cvtsi2ss xmm0,eax
ret
sumAsFlt ENDP
END start
the site is not available :icon_eek: tried it from different countries
QuoteThis site can't be reached
www.terraspace.co.uk's server DNS address could not be found.
Search Google for terraspace co uk uasm
ERR_NAME_NOT_RESOLVED
QuoteUnable to connect
Firefox can't establish a connection to the server at www.terraspace.co.uk.
The site could be temporarily unavailable or too busy. Try again in a few moments.
If you are unable to load any pages, check your computer's network connection.
If your computer or network is protected by a firewall or proxy, make sure that Tor Browser is permitted to access the Web.
F'ing hosting companies... it says the domain has expired on WHOIS, yet on their control panel it's paid up for another 2 years... wtf... time to fight
Good sign
Looks like you've been noticed
Congrats and Take care
Quote from: johnsa on December 08, 2017, 03:59:04 AM
F'ing hosting companies... it says the domain has expired on WHOIS, yet on their control panel it's paid up for another 2 years... wtf... time to fight
After experimenting with many others, I am using contabo.com (they are German :bgrin:) and am happy for the last couple of years. They have plans starting from a couple of bucks per month.
My plan is a VPS with windows and 2 extra IP, 1000 GB storage space, 4 cores, 14 GB RAM - all about 20 euro/month.
Hi johnsa,
Thanks for your efforts. I will wait for your site to be online so no worries. I know that those hosting companies can sometimes be real headaches. Take your time to fix the hosting issue and thanks again.
John,
Easiest solution: Zip up the exe only and post it here temporarily.
Why not just mirror the package releases on github? create a 'releases' folder on the main repo, put stuff in there and/or additionally add a 'Latest Release' on the releases page and have the packages linked there to the releases folder
Releases page:
tag: latest
Title: Latest Releases
## UASM


?raw=true in the url allows the file to be downloaded rather than github redirecting to the file and trying to display it then failing - because its binary and cant display raw.
Also you can create a github page - terraspace.github.io or uasm.github.io to mirror most of the information on terraspace.co.uk: see https://pages.github.com/ for details
I'd thought about, it's useful to have the extra copy of the page and information on github directly with releases... I shall do that :)
Hi all,
Packages and git have been updated to 2.46.3 dated 8th Dec.
This includes all the required fixes and a new option hlcall:{on|off} to disable the c style function calling and object/pointer invocations. It's enabled by default.
Cheers
deleted
Great minds ... and all paths lead to Rome .. I noticed you'd published an update about function pointer invocations at about exactly the same time! :t
Hi johnsa,
thanks for the Great Job! XP version waiting for updates? Its not on the list of common releases, although the link to the previous version works.
The 32bit version is built with WinXP compatibility mode so that should work as-is on XP.
John
Congrats, John & Habran :icon14:
Works perfectly with today's version of MasmBasic (http://masm32.com/board/index.php?topic=94.0); I had to add a little switch, as agreed with John. RichMasm will try to install UAsm64 2.46 if there is no \Masm32\bin\uasm64.exe on your disk. This works fine when launching RichMasm from a drive different from C.
Hi habran and johnsa,
I am trying to use high level calling syntax with COM. Converting a simple Masm COM example :
IActiveDesktop STRUCT
QueryInterface dd ?
AddRef dd ?
Release dd ?
ApplyChanges dd ?
GetWallpaper dd ?
SetWallpaper dd ?
GetWallpaperOptions dd ?
SetWallpaperOptions dd ?
GetPattern dd ?
SetPattern dd ?
GetDesktopItemOptions dd ?
SetDesktopItemOptions dd ?
AddDesktopItem dd ?
AddDesktopItemWithUI dd ?
ModifyDesktopItem dd ?
RemoveDesktopItem dd ?
GetDesktopItemCount dd ?
GetDesktopItem dd ?
GetDesktopItemByID dd ?
GenerateDesktopItemHtml dd ?
AddUrl dd ?
GetDesktopItemBySource dd ?
IActiveDesktop ENDS
Probably, my convertion is not correct so I need your help here :
COMINTERFACE IActiveDesktop
CVIRTUAL ApplyChanges ,DWORD, :DWORD
CVIRTUAL GetWallpaper ,DWORD, :PTR, :DWORD, :DWORD
CVIRTUAL SetWallpaper ,DWORD, :PTR, :DWORD
CVIRTUAL GetWallpaperOptions ,DWORD, :DWORD, :DWORD
CVIRTUAL SetWallpaperOptions ,DWORD, :DWORD, :DWORD
CVIRTUAL GetPattern ,DWORD,:PTR, :DWORD, :DWORD
CVIRTUAL SetPattern ,DWORD, :PTR, :DWORD
CVIRTUAL GetDesktopItemOptions ,DWORD, :DWORD, :DWORD
CVIRTUAL SetDesktopItemOptions ,DWORD, :DWORD, :DWORD
CVIRTUAL AddDesktopItem ,DWORD, :DWORD, :DWORD
CVIRTUAL AddDesktopItemWithUI ,DWORD, :HWND, :DWORD, :DWORD
CVIRTUAL ModifyDesktopItem ,DWORD, :DWORD, :DWORD
CVIRTUAL RemoveDesktopItem ,DWORD, :DWORD, :DWORD
CVIRTUAL GetDesktopItemCount ,DWORD, :LPINT, :DWORD
CVIRTUAL GetDesktopItem ,DWORD, :DWORD, :DWORD, :DWORD
CVIRTUAL GetDesktopItemByID ,DWORD, :PTR, :DWORD, :DWORD
CVIRTUAL GenerateDesktopItemHtml ,DWORD, :PTR, :DWORD, :DWORD
CVIRTUAL AddUrl ,DWORD, :DWORD, :PTR, :DWORD, :DWORD
CVIRTUAL GetDesktopItemBySource ,DWORD, :PTR, :DWORD, :DWORD
ENDCOMINTERFACE
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\ole32.inc
include \masm32\macros\macros.asm
include SetWallpaper.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\ole32.lib
LPad TYPEDEF PTR IActiveDesktop
.data
CLSID_IActiveDesktop GUID sCLSID_IActiveDesktop
IID_IActiveDesktop GUID sIID_IActiveDesktop
WSTR DesktopImg,"test.bmp"
pAD LPad 0
.data?
wpo WALLPAPEROPT <>
.code
start:
invoke CoInitialize,NULL
invoke CoCreateInstance,ADDR CLSID_IActiveDesktop,NULL,\
CLSCTX_INPROC_SERVER,ADDR IID_IActiveDesktop,ADDR pAD
mov edx,OFFSET wpo
mov WALLPAPEROPT.dwSize[edx],SIZEOF(WALLPAPEROPT)
mov WALLPAPEROPT.dwStyle[edx],WPSTYLE_CENTER
pAD->SetWallpaper(OFFSET DesktopImg,0)
coinvoke pAD,IActiveDesktop,SetWallpaper,OFFSET DesktopImg,0
coinvoke pAD,IActiveDesktop,SetWallpaperOptions,OFFSET wpo,0
coinvoke pAD,IActiveDesktop,ApplyChanges,AD_APPLY_ALL
coinvoke pAD,IActiveDesktop,Release
invoke CoUninitialize
invoke ExitProcess,0
END start
The error message :
SetWallpaper.asm(41) : Error A2049: Invalid instruction operands
_VCOMINVOKE(10)[SetWallpaper.asm]: Macro called from
SetWallpaper.asm(41): Main line code
SetWallpaper.asm: 55 lines, 1 passes, 170 ms, 0 warnings, 1 errors
Line 41 seems to be the problem :
pAD->SetWallpaper(OFFSET DesktopImg,0)
I would like test the arrow operator ( -> ) and the built-in macro _INVOKE in two different versions of the source code above. How should I use the the _INVOKE macro to call COM methods in my example code? Another question, can I use the structure IActiveDesktop instead of a COMINTERFACE definition while specifying the arrow operator or the _INVOKE macro?
Hi,
I'll test out this example and see what the issue is with that line, I suspect it may be to do with using the OFFSET operator in the macro.
The pointer syntax (->) can only be used with OINTERFACE, CLASS and COMINTERFACE (internally these types are tracked as being different from regular structures and different from each other).
In the case of the ointerface or class the vtable exists inside the instance itself, where-as with com the object contains a pointer to the vtable. So the keep the syntax consistent it handles them differently by adding extra indirection in the case of COM. Using the ointerface or class with -> requires use of a vtable (OPTION VTABLE:ON) where-as for performance reasons if you have a class that you know is not going to be dynamically modified, and hence no reason to go via a vtable, with that off the call removes the extra indirection and goes straight to the method call.
I'll get back to you asap with a fix for the offset issue.
On another note, the _V, _INVOKE and other macros that are built-in deal entirely with the OO features. COM having the extra indirection required slightly different handling so internally uses _VCOMINVOKE and _VCOM.
Assuming you don't wanted nested calls, then using _VCOMINVOKE or _INVOKE(for normal OO) is pretty straightforward as per the example in the manual and samples folder.
Quote from: johnsa on December 11, 2017, 08:24:33 PMThe pointer syntax (->) can only be used with...
It's very unfortunate that the authors of MASM used the <> as a reserved word; same for the exclamation mark. OTOH, there was not so much choice: {any better?} ^or this^ %no good% §advocates need these§ @mail@ ...
I know :( That's why i intentionally forced it's usage to be limited. In the normal situation with < > the tokenizer knows it's in a literal so <......-> is fine, but at least for now I'd like to keep such a major divergence from traditional asm syntax quite contained.
Hi johnsa,
This one produces a syntax error message :
_INVOKE pAD,SetWallpaper,OFFSET DesktopImg,0
SetWallpaper.asm(41) : Error A2210: Syntax error: _INVOKE
I could not find any reference to the _VCOMINVOKE macro in the manual uasm246_ext.pdf. No example using this macro.
Assembling the example oo2.asm, I get the following error messages :
uasm64 -win64 -c -Zp8 -Zi -Zd -Zf oo2.asm
UASM v2.46, Dec 8 2017, Masm-compatible assembler.
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.
oo2.asm(37) : Error A2221: Missing macro argument: CVIRTUAL, parameter 2
oo2.asm(38) : Error A2221: Missing macro argument: CVIRTUAL, parameter 2
oo2.asm: 274 lines, 1 passes, 153 ms, 0 warnings, 2 errors
To fix this issue, I modified the two lines below.
OINTERFACE Entity
CVIRTUAL PrintName
CVIRTUAL SetName
ENDOINTERFACE
The corrected version :
OINTERFACE Entity
CVIRTUAL PrintName, <>
CVIRTUAL SetName, <>
ENDOINTERFACE
You are right about oo2.asm, I must have forgot to update that sample after adding the return type to CVIRTUAL. I've updated it myside so it's correct and will be in the next package update.
_INVOKE and _I are designed to bypass the VTABLE altogether, their syntax is as follows:
_INVOKE MACRO className : REQ, method : REQ, objPtr : REQ, args : VARARG
_I MACRO className : REQ, method : REQ, objPtr : REQ, args : VARARG
_INVOKE would be for normal outer calls, and _I would be used inline.
_INVOKE MyClass, MyMethod, pObj, ......
The _V equivalents access the object through the vtable and have slightly different syntax:
_VINVOKE MACRO pInterface : REQ, Interface : REQ, Function : REQ, args : VARARG
_V MACRO pInterface : REQ, Interface : REQ, Function : REQ, args : VARARG
_VINVOKE pObj, MyClass, MyMethod, ....
I didn't include any references to VCOM or VCOMINVOKE in the documents as I didn't think anyone would call those directly / they are available.. but they're sort of "internal" to implement the COMINTERFACE and method invocation against it.
They're definitions are:
_VCOMINVOKE MACRO pInterface : REQ, Interface : REQ, Function : REQ, args : VARARG
_VCOM MACRO pInterface : REQ, Interface : REQ, Function : REQ, args : VARARG
So basically the same as the vtable based OO functions (VINVOKE and V) but they perform a double indirection.
I will update the packages shortly with fixes.
Packages are updated, oo2.asm is fixed and the 32bit COM call issue should be fixed.
Hi johnsa,
Thanks for the update. Here are the results of my tests.
Trying the _VCOMINVOKE macro :
_VCOMINVOKE pAD,IActiveDesktop,SetWallpaper,ADDR DesktopImg,0
_VCOMINVOKE pAD,IActiveDesktop,SetWallpaperOptions,OFFSET wpo,0
_VCOMINVOKE pAD,IActiveDesktop,ApplyChanges,AD_APPLY_ALL
_VCOMINVOKE pAD,IActiveDesktop,Release
Uasm is assembling my code without any error messages but the executable is crashing on Windows 7.
Investigating the case with the /EP option :
uasm32.exe /EP /c /coff SetWallpaper.asm
mov eax, pAD
mov eax,[eax]
invoke(_IActiveDesktop_SetWallpaperPto PTR[eax].IActiveDesktop.SetWallpaper), pAD, ADDR DesktopImg,0
mov eax, pAD
mov eax,[eax]
invoke(_IActiveDesktop_SetWallpaperOptionsPto PTR[eax].IActiveDesktop.SetWallpaperOptions), pAD, OFFSET wpo,0
mov eax, pAD
mov eax,[eax]
invoke(_IActiveDesktop_ApplyChangesPto PTR[eax].IActiveDesktop.ApplyChanges), pAD, AD_APPLY_ALL
mov eax, pAD
mov eax,[eax]
invoke(_IActiveDesktop_ReleasePto PTR[eax].IActiveDesktop.Release), pAD
The pAD parameter should not be pushed to the stack.
Disassembling the object file with objconv :
_VCOMINVOKE pAD,IActiveDesktop,SetWallpaper,ADDR DesktopImg,0
mov eax, dword ptr [_pAD]
mov eax, dword ptr [eax]
push 0
push offset _DesktopImg
push dword ptr [_pAD] ; <--- This line causing problem
call dword ptr [eax+14H]
Assuming that _VCOM is equivalent to _VCOMINVOKE :
_VCOMINVOKE MACRO pInterface : REQ, Interface : REQ, Function : REQ, args : VARARG
_VCOM MACRO pInterface : REQ, Interface : REQ, Function : REQ, args : VARARG
Replacing _VCOMINVOKE with _VCOM :
SetWallpaper.asm(41) : Error A2210: Syntax error: _VCOM
SetWallpaper.asm(43) : Error A2210: Syntax error: _VCOM
SetWallpaper.asm(45) : Error A2210: Syntax error: _VCOM
SetWallpaper.asm(47) : Error A2210: Syntax error: _VCOM
SetWallpaper.asm: 53 lines, 1 passes, 4 ms, 0 warnings, 4 errors
Testing the arrow operator with OPTION VTABLE:ON and OPTION VTABLE:OFF
pAD->SetWallpaper(OFFSET DesktopImg,0)
pAD->SetWallpaperOptions(OFFSET wpo,0)
pAD->ApplyChanges(AD_APPLY_ALL)
pAD->Release()
pAD is again pushed to the stack :
mov eax, pAD
mov eax,[eax]
invoke(_IActiveDesktop_SetWallpaperPto PTR[eax].IActiveDesktop.SetWallpaper), pAD, OFFSET DesktopImg,0
mov eax, pAD
mov eax,[eax]
invoke(_IActiveDesktop_SetWallpaperOptionsPto PTR[eax].IActiveDesktop.SetWallpaperOptions), pAD, OFFSET wpo,0
mov eax, pAD
mov eax,[eax]
invoke(_IActiveDesktop_ApplyChangesPto PTR[eax].IActiveDesktop.ApplyChanges), pAD, AD_APPLY_ALL
mov eax, pAD
mov eax,[eax]
invoke(_IActiveDesktop_ReleasePto PTR[eax].IActiveDesktop.Release), pAD
Hi,
I've just written the same code in C for comparison and run both. Your code works for me here and sets the desktop wallpaper.
The C-code looks as follows for a COM invocation:
pAD->SetWallpaper((PCWSTR)&DesktopImg, 0);
013D17E4 6A 00 push 0
013D17E6 8D 45 C0 lea eax,[DesktopImg]
013D17E9 50 push eax
013D17EA 8B 4D F4 mov ecx,dword ptr [pAD]
013D17ED 8B 11 mov edx,dword ptr [ecx]
013D17EF 8B 45 F4 mov eax,dword ptr [pAD]
013D17F2 50 push eax
013D17F3 8B 4A 14 mov ecx,dword ptr [edx+14h]
013D17F6 FF D1 call ecx
and from uasm:
_VCOMINVOKE pAD,IActiveDesktop,SetWallpaper,ADDR DesktopImg,0
; pAD->SetWallpaper(OFFSET DesktopImg,0) identical code generated
01081031 mov eax,dword ptr ds:[01083032h]
01081036 mov eax,dword ptr [eax]
01081038 push 0
0108103A push 1083020h
0108103F push dword ptr ds:[1083032h]
01081045 call dword ptr [eax+14h]
As you can see in the C version, we have PUSH 0, PUSH ADDRESS OF ImageName, and most importantly.. the THIS ptr...
013D17EF 8B 45 F4 mov eax,dword ptr [pAD]
013D17F2 50 push eax
So we're doing it the same and both have identical results for me in C and ASM.
C code for reference:
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
int main()
{
IActiveDesktop *pAD = NULL;
WALLPAPEROPT wpo;
wchar_t DesktopImg[] = L"apicture.jpg";
CoInitializeEx(0,COINIT_APARTMENTTHREADED);
CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pAD);
memset(&wpo, 0, sizeof(WALLPAPEROPT));
wpo.dwSize = sizeof(WALLPAPEROPT);
wpo.dwStyle = WPSTYLE_CENTER;
pAD->SetWallpaper((PCWSTR)&DesktopImg, 0);
pAD->Release();
CoUninitialize();
return 0;
}
Quote from: johnsa on December 13, 2017, 07:53:50 AM
C code for reference:
I love it :icon_mrgreen:
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
Tmp.cpp
c:\program files (x86)\microsoft visual studio 10.0\vc\include\codeanalysis\sourceannotations.h(78): warning C4467: usage of ATL attributes is deprecated
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\ShlObj.h(1151): warning C4091: 'typedef ': ignored on left of 'tagGPFIDL_FLAGS' when no variable is declared
Tmp.cpp(10): error C2065: 'IActiveDesktop': undeclared identifier
Tmp.cpp(10): error C2065: 'pAD': undeclared identifier
Tmp.cpp(11): error C2065: 'WALLPAPEROPT': undeclared identifier
Tmp.cpp(11): error C2146: syntax error: missing ';' before identifier 'wpo'
Tmp.cpp(11): error C2065: 'wpo': undeclared identifier
Tmp.cpp(13): warning C4129: 'M': unrecognized character escape sequence
Tmp.cpp(13): warning C4129: 'A': unrecognized character escape sequence
Tmp.cpp(13): warning C4129: 'C': unrecognized character escape sequence
Tmp.cpp(16): error C2065: 'pAD': undeclared identifier
Tmp.cpp(18): error C2065: 'wpo': undeclared identifier
Tmp.cpp(18): error C2065: 'WALLPAPEROPT': undeclared identifier
Tmp.cpp(19): error C2065: 'wpo': undeclared identifier
Tmp.cpp(19): error C2228: left of '.dwSize' must have class/struct/union
Tmp.cpp(19): note: type is 'unknown-type'
Tmp.cpp(19): error C2065: 'WALLPAPEROPT': undeclared identifier
Tmp.cpp(20): error C2065: 'wpo': undeclared identifier
Tmp.cpp(20): error C2228: left of '.dwStyle' must have class/struct/union
Tmp.cpp(20): note: type is 'unknown-type'
Tmp.cpp(20): error C2065: 'WPSTYLE_CENTER': undeclared identifier
Tmp.cpp(22): error C2065: 'pAD': undeclared identifier
Tmp.cpp(22): error C2227: left of '->SetWallpaper' must point to class/struct/union/generic type
Tmp.cpp(22): note: type is 'unknown-type'
Tmp.cpp(24): error C2065: 'pAD': undeclared identifier
Tmp.cpp(24): error C2227: left of '->Release' must point to class/struct/union/generic type
Tmp.cpp(24): note: type is 'unknown-type'
What's in your stdafx.h? Is the wpo needed at all?
MSDN says it's supported under XP and earlier - does it work on Win7 and higher...? I can build it in assembler, I get S_OK all the time but no wallpaper is set :(
I'm on Windows 10 and it seems to work for me, there is more code however to complete the operation properly, i believe you need to apply the change..
something along these lines (and this also lists the required headers) :
#include "windows.h"
#include "wininet.h"
#include "shlobj.h"
#include "wchar.h"
#include <iostream>
void SetWallpaper(LPCWSTR file){
CoInitializeEx(0,COINIT_APARTMENTTHREADED);
IActiveDesktop* desktop;
HRESULT status = CoCreateInstance(CLSID_ActiveDesktop,NULL,CLSCTX_INPROC_SERVER,IID_IActiveDesktop,(void**)&desktop);
WALLPAPEROPT wOption;
ZeroMemory(&wOption, sizeof(WALLPAPEROPT));
wOption.dwSize=sizeof(WALLPAPEROPT);
wOption.dwStyle = WPSTYLE_CENTER;
status = desktop->SetWallpaper(file,0);
wcout << status << endl;
status = desktop->SetWallpaperOptions(&wOption,0);
wcout << status << endl;
status = desktop->ApplyChanges(AD_APPLY_ALL);
wcout << status << endl;
desktop->Release();
CoUninitialize();
}
int wmain(int argc, wchar* argv[]){
if(argc<=1){
wcout << "use: " << argv[0] <<" path_to_pic.bmp" <<endl;
}else{
wchar_t* file = argv[1];
SetWallpaper(file);
}
getchar();
return 0;
}
Thanks, John, I'll check it tomorrow :icon14:
My current code is here (http://masm32.com/board/index.php?topic=6483.msg72315#msg72315).
Updated packages will be publish shortly for 2.46.5.
I've started including the sub version number on the site so it's easier to see which is current , apart from checking the date.
Changes are:
1) Included a new oo3.sample that shows how to invoke methods from inside methods using thisPtr and pointer syntax.
mov rsi,thisPtr
assume rsi:PTR Person
mov rax,lstrlen([rcx].pName)
WriteConsole( [rsi].handle, [rsi].pName, eax, ADDR bWritten, NULL )
assume rsi:NOTHING
; calls to other instance methods with pointer syntax.
; -> Because the METHOD declaration sets the prototype, you cannot forward reference methods.
thisPtr->SetName("New name")
mov rcx,thisPtr
mov rax,[rcx].handle
mov rbx,[rcx].pName
invoke WriteConsole, rax, rbx, 8, ADDR bWritten, NULL
; calls to other instance methods with pointer syntax using a register.
lea rcx,thisPtr
[rcx].Person->SetName("New name")
2) Added a bunch of new regression tests and fixed some evex support queries around usage in macros, including decorators { } being passed in and out of macros and equate substitution in evex expressions.
vsubpd zmm0 {KMASK}, zmm1, zmm2 ; direct macro substitution works.
;--------------------------------------------------------
znoconst_rounding_single_nottp MACRO zmmval, zmmcarry, kwritemask
zfmsubpd zmmcarry, {kwritemask}, zmmval, zmm24, zmm20
zfmsubpd zmm16, {kwritemask}, zmmcarry, zmm26, zmm22
vsubpd zmmval {kwritemask}, zmmval, zmm16
ENDM
;--------------------------------------------------------
znoconst MACRO zmmval, kwritemask
vsubpd zmmval {kwritemask}, zmmval, zmm16
; multiple elements can be substituted in the macro, include
; placeholder for register and decorator.
vsubpd zmm2 {kwritemask}, zmmval, zmm16
; register + expanded decorator from macro parameter works.
3) Added optimisation, previously a 0 valued immediate would be optimised to an xor during invoke, now the same applies to zero-valued equates.
Another note to include is that I've also added support for the C style calls to handle equates.
We parse the high level calls before any form of expansion or substitution on the line, but can now handle something like:
WriteConsoleA EQU <__imp_WriteConsoleA>
WriteConsole EQU <WriteConsoleA>
WriteConsole( ... )
By traversing the equates to see if they evaluate to a real procedure either locally defined in the project or marked as external.
Hi johnsa,
Thanks for your help :t I got it to work. The pointer to the interface ( pAD ) should be passed to the stack, that's right, I was mistaken.
Both of the syntaxes are working fine :
pAD->SetWallpaper(OFFSET DesktopImg,0)
pAD->SetWallpaperOptions(OFFSET wpo,0)
pAD->ApplyChanges(AD_APPLY_ALL)
pAD->Release()
_VCOMINVOKE pAD,IActiveDesktop,SetWallpaper,ADDR DesktopImg,0
_VCOMINVOKE pAD,IActiveDesktop,SetWallpaperOptions,OFFSET wpo,0
_VCOMINVOKE pAD,IActiveDesktop,ApplyChanges,AD_APPLY_ALL
_VCOMINVOKE pAD,IActiveDesktop,Release
Packages and repos updated.
2.46.5 / 14th Dec 2017.
Cheers :)
John
OK for my big sources :t
It's just a dream for an assembler language programmer :t Thanks!
Hi johnsa,
Thanks for the new release. Testing the handling of the equates, I get the following error messages :
.386
.model flat,stdcall
option casemap:none
MessageBoxA EQU <_MessageBoxA@16>
MessageBox EQU <MessageBoxA>
ExitProcess EQU <_ExitProcess@4>
MB_OK equ 0
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
.data
_message db 'Hello world!',0
_title db 'Hello',0
.code
start:
MessageBox(0,ADDR _message,ADDR _title,MB_OK)
ExitProcess(0)
END start
UASM v2.46, Dec 14 2017, Masm-compatible assembler.
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.
MessageBox.asm(24) : Error A2210: Syntax error: _MessageBox@16
MessageBox.asm(26) : Error A2210: Syntax error: _ExitProcess@4
MessageBox.asm: 28 lines, 1 passes, 5 ms, 0 warnings, 2 errors
The equates are fine, you need a valid prototype though, so put this before the equates:
_MessageBox@16 PROTO :DWORD, :DWORD, :DWORD, :DWORD
_ExitProcess@4 PROTO :DWORD
Hi johnsa,
Thanks. The version below works too :
.386
.model flat,stdcall
option casemap:none
MessageBoxA PROTO :DWORD, :DWORD, :DWORD, :DWORD
ExitProcess PROTO :DWORD
MessageBox EQU <MessageBoxA>
MB_OK equ 0
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
.data
_message db 'Hello world!',0
_title db 'Hello',0
.code
start:
MessageBox(0,ADDR _message,ADDR _title,MB_OK)
ExitProcess(0)
END start