The MASM Forum

64 bit assembler => ASMC Development => Topic started by: nidud on January 10, 2017, 03:13:07 AM

Title: Asmc source and binaries
Post by: nidud on January 10, 2017, 03:13:07 AM
Source and binaries for Asmc is now available at GitHub:

https://github.com/nidud/asmc

The package is configured to work "out of the box" but it's recommended to tweak the console settings for optimal performance.

Console applications is best managed by simply adding a shortcut to the program, in this case to the file DZ.EXE in the root directory of the package. After the shortcut is created, right-click and select Properties. Open the Font tab and select a proper font and font size for the console window.

I didn't find the keyboard settings directly in the Win7 Control panel but the search[keyboard] option found the Keyboard Properties tab. The keyboard is normally slow in the console so the Keyboard Delay should be set to Short and Repeat Rate to Fast for best performance.

The environment for the shell is set as follows:
Code: [Select]
[Environ]
0=AsmcDir=%DZ%
1=LIB=%DZ%\lib
2=INCLUDE=%DZ%\include
3=WATCOM=C:\WATCOM

[Path]
0=%AsmcDir%\bin
1=C:\VC\bin
2=%WATCOM%\BINNT
3=%WATCOM%\BINW
4=C:\jWasm
5=%PATH%

Note that Watcom provide clones for some of the MS tools, so VC should for this reason be defined before Watcom.
Title: Re: Asmc source and binaries
Post by: caballero on January 10, 2017, 03:38:42 AM
What is asmc if I may ask?
Title: Re: Asmc source and binaries
Post by: nidud on January 10, 2017, 04:43:27 AM
What is asmc if I may ask?

Asmc is basically a modified version of JWasm made in 2011. It was used as a TASM clone to maintain some DOS tools at the time.

https://github.com/nidud/asmc/blob/master/source/dos/tasm/tasm.asm

I later added some enhancement to the HLL section and a few other things, so I have been playing with it for some time. However the features added so far seems stable so in that sense the playtime has come to a conclusion in a somewhat usable product.

Some more info from the help file:

Asmc Macro Assembler Reference

This lists some of the differences between Asmc, JWasm, and Masm.

Asmc Extensions

The main goal with Asmc is an attempt to provide more readability to the assembly language based on Masm syntax but at the same time keep compatibility with existing source code. In order to achieve this some of the main core of the assembler has to be rewritten and the HLL section enhanced as discussed below.

Parsing of labels

All expansions are pre-processed by the assembler and this may expand macros and other directives before labels. If a macro is added at the same line as a label this may fail.

Example:

Code: [Select]
foo macro reg
bswap reg
exitm <reg>
endm

do: mov eax,foo( eax )
...
mov ecx,"3210"
jmp do

As a result the code produced by the macro will be expanded above the label and thus the jump will fail.

Code: [Select]
bswap ecx
do: mov eax,ecx
...

Asmc will expand the line left to right in this case.

Expansion of macros

The label issue becomes a problem in the HLL section where labels are created later:

   .WHILE macro(...)

Asmc will for this reason delay expansion of macros in some of the HLL directives until labels are created. This include .WHILE, .ELSEIF, and .CASE.

The invoke directive

In Asmc a macro is handled at the same level as a procedure. The header file may then control the expansion:
Code: [Select]
ifdef __INLINE__
strlen macro string
...
endm
else
strlen proto :dword
endif

This is achieved by simply excluding invoke as appose to allow invocations of macros.

   strlen( esi )


Asmc sees the combination of a procedure followed by an open bracket as invoke. Empty brackets will be given special handling if the token in front is not a macro.
Code: [Select]
plabel proto
extern elabel:dword
clabel:
call eax
call plabel
call elabel
call clabel
call xlabel

eax()
plabel()
elabel()
clabel()
xlabel()
xlabel:

This simple solution avoids breaking any existing code with a few exceptions: Masm allows brackets to access memory.

   .if edx < foo( 1 )
   ; MASM: cmp edx,foo+1
   ; ASMC: invoke foo, 1 : cmp edx,eax

So square brackets should be used for accessing memory and round brackets to execute. However, an error must then be issued if Asmc extensions are turned off and labels are accessed using round brackets to ensure compatibility.

The inside of brackets may be recursive used at any length including C-strings. However, the return code for a procedure is [R|E]AX so there is a limit with regards to OR/AND testing of nested functions.

   .if foo( bar( 1 ), 2 ) == TRUE


Handling of strings

Given "quoted strings" may be used as arguments, or in general as a const value, C-strings are limited to be used inside brackets of a procedure.

   .if fopen( "readme.txt", "rt" )


@CStr( string )

Macro function that creates a string in the .DATA segment. The macro accepts C-escape characters in the string. Strings are added to a stack and reused if duplicated strings are found. The macro returns offset string.

Example:
Code: [Select]
mov eax,@CStr( "\tCreate a \"C\" string: %s%d\n" )
mov ebx,@CStr( "string: %s%d\n" )
mov ecx,@CStr( "%s%d\n" )
mov edx,@CStr( "%d\n" )
mov edi,@CStr( "\n" )

Generated code:
Code: [Select]
.data
DS0000 db 9,"Create a ",'"',"C",'"'," string: %s%d",10,0
.code
mov eax,offset DS0000
mov ebx,offset DS0000[14]
mov ecx,offset DS0000[22]
mov edx,offset DS0000[24]
mov edi,offset DS0000[26]

@Date

The system date in the format yyyy-mm-dd (text macro).

.SWITCH

The switch comes in three main variants: a structured switch, as in Pascal, which takes exactly one branch, an unstructured switch, as in C, which functions as a type of goto, and a control table switch with the added possibility of testing for combinations of input values, using boolean style AND/OR conditions, and potentially calling subroutines instead of just a single set of values.

The control table switch is declared with no arguments and each .CASE directive does all the testing.
Code: [Select]
    .switch
      .case strchr( esi, '<' )
      .case strchr( esi, '>' )
    jmp around
      ...
    .endsw

The unstructured switch works as a regular C switch where each .CASE directive is just a label.
Code: [Select]
    .switch eax
      .case 0: .repeat : movsb
      .case 7: movsb
      .case 6: movsb
      .case 5: movsb
      .case 4: movsb
      .case 3: movsb
      .case 2: movsb
      .case 1: movsb : .untilcxz
    .endsw

The structured switch works as a regular Pascal switch where each .CASE directive is a closed branch.
Code: [Select]
    .switch eax
      .case 1: printf("Gold medal")
      .case 2: printf("Silver medal")
      .case 3: printf("Bronze medal")
      .default
  printf("Better luck next time")
    .endsw

.CASE

Case opens a case statement. The case statement compares the value of an ordinal expression to each selector, which can be a constant, a subrange, or a list of them separated by commas.

The selector field is separated from action field by Colon or a new line.
Code: [Select]
.CASE 1: mov ax,2 : .ENDC
.CASE 2
      mov ax,3
      .ENDC
.CASE al
.CASE 0,1,4,7
.CASE 0..9

In the control table switch .CASE is equal to .IF:
Code: [Select]
.CASE al
.CASE ax <= 2 && !bx

.ENDC

.ENDC closes a .CASE statement.

The name was separated from BREAK to have more flexibility with regards to control flow of loops. However, ENDC have the same qualities as BREAK and thus can be used in combination with .IF:

   .ENDC .IF al == 2


.DEFAULT

.DEFAULT executes when none of the other cases match the control expression.

.ENDSW

.ENDSW closes a .SWITCH statement.
Title: Re: Asmc source and binaries
Post by: HSE on January 10, 2017, 06:12:10 AM
Hi Nidud!!

Just testing a ObjAsm32 project (wich have macros .for .switch, etc) I think /Xc is not disabling .switch. 

Of course if the option disable .if, .while, .repeat, etc there is another problem.

Regards.
Title: Re: Asmc source and binaries
Post by: nidud on January 10, 2017, 07:41:37 AM
Just testing a ObjAsm32 project (wich have macros .for .switch, etc) I think /Xc is not disabling .switch. 

The extended directives will be a problem if you use them in this way, so I have to look into that.

Code: [Select]
ifdef __ASMC__
    option renamekeyword: <.switch>=@@switch
    option renamekeyword: <.case>=@@case
    option renamekeyword: <.endsw>=@@endsw
endif

Or the reverse logic:
Code: [Select]
ifndef __ASMC__
    option dotname

.switch macro arg
...
endm
.case macro arg
...
endm
.endsw macro
...
endm
endif
Title: Re: Asmc source and binaries
Post by: nidud on January 10, 2017, 07:59:02 AM
So, the full list:
Code: [Select]
ifdef __ASMC__
    option asmc:off
    option nokeyword:<.switch>
    option nokeyword:<.case>
    option nokeyword:<.endc>
    option nokeyword:<.default>
    option nokeyword:<.endsw>
    option nokeyword:<.ifb>
    option nokeyword:<.ifw>
    option nokeyword:<.ifd>
    option nokeyword:<.assert>
    option nokeyword:<.assertb>
    option nokeyword:<.assertw>
    option nokeyword:<.assertd>
endif
Title: Re: Asmc source and binaries
Post by: nidud on January 10, 2017, 09:04:29 AM
I updated the source and binary

https://github.com/nidud/asmc/commit/571c0913123d57ba2320b263d82f664f6d274ad1

test case using the switch /Xc
Code: [Select]
.486
.model flat
.code

        option dotname

.switch macro
endm
.case macro
endm
.endc macro
endm
.default macro
endm
.endsw macro
endm
.ifb macro
endm
.ifw macro
endm
.ifd macro
endm
.assert macro
endm
.assertb macro
endm
.assertw macro
endm
.assertd macro
endm

END
Title: Re: Asmc source and binaries
Post by: HSE on January 10, 2017, 02:17:37 PM
/Xc work perfect now  :t

With that option ObjAsm32 work fantastic.  :eusa_clap: :eusa_clap:

Apparently full compatiblity with M$, no length line problems, nor macro nest levels problems.   

                              (http://www.thebort.com/www/Smileys/default/th_beer.gif)
Title: Re: Asmc source and binaries
Post by: nidud on January 10, 2017, 09:23:08 PM
 :t

This do however separate the switch /Xc from the OPTION ASMC:[ON|OFF]

The off option will keep the directives and the switch will still work, but using extended features will generate an error:
Code: [Select]
        foo proto
        option asmc:off
        .switch
          .case  (eax || edx) && ecx : nop : .endc
          .case !(eax || edx) && ecx : nop : .endc
          .case foo()
 error A2008: syntax error : )
Title: Re: Asmc source and binaries
Post by: HSE on January 12, 2017, 01:06:55 AM
Very interesting! With the nokeyword option it's posible to use the same command line options for M$ or HJwasm. In RadAsm I only change the assembler name  :t 
Title: Re: Asmc source and binaries
Post by: powershadow on January 15, 2017, 10:56:12 PM
Hi nidud.
Just downloaded asmc.exe for test it, and I already have a question.
Command-line /I - not supported anymore? I need use environment variable "include"?
I see asmc just add path from "/I" to the path of my project, this is incorrect.

Simple example:

.386
.model flat,stdcall
include windows.inc ; <<<< fatal error A1000: cannot open file: windows.inc

Command-line:
c:\jwasm\bin32\asmc.exe /c /coff /cp /I"c:\jwasm\Include" "test.asm"

It is bug or feature?
Title: Re: Asmc source and binaries
Post by: jj2007 on January 15, 2017, 11:00:13 PM
include windows.inc ; <<<< fatal error A1000: cannot open file: windows.inc

Use \masm32\include\windows.inc

Or, even better:
include \masm32\include\masm32rt.inc

There is a reason why (almost) everybody here uses the \full\path without the drive letters: it works.
Title: Re: Asmc source and binaries
Post by: powershadow on January 15, 2017, 11:15:44 PM
There is a reason why (almost) everybody here uses the \full\path without the drive letters: it works.

Thanks for reply. I know it. I just ask if this bug or feature. I just opened example from masm32 and can't compile them without modify.

masm - file found.
jwasm - file found.
hjwasm - file found.
asmc - file NOT found, strange.
Title: Re: Asmc source and binaries
Post by: jj2007 on January 15, 2017, 11:24:24 PM
OK, I see. This works:
Code: [Select]
C:\Masm32\MasmBasic\AscUser>\masm32\bin\asmc /c /coff /I"\Masm32\Include" testAsmC.asm
Doszip Macro Assembler Version 2.22
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.

 Assembling: testAsmC.asm

... with this source:
Code: [Select]
.386
.model flat,stdcall
;include windows.inc ; <<<< fatal error A1000: cannot open file: windows.inc
.code
start:
  retn

end start

However, I get plenty of errors in all assemblers when trying to use both the command line include and the one after .model

Btw what's the state of play in your other thread (http://masm32.com/board/index.php?topic=5896.msg62670#msg62670)? All problems fixed?
Title: Re: Asmc source and binaries
Post by: nidud on January 16, 2017, 02:58:17 AM
Confirmed.

Quotes in command line arguments are not expanded in the same way in the RTL now used, so additional expansion was needed for switch -D, -I and -Fi used with -I"quoted text".

Link to the added changes:
https://github.com/nidud/asmc/commit/5471d03bbfced345c50b95dcecb1e6957fe18a95
Title: Re: Asmc source and binaries
Post by: powershadow on January 16, 2017, 07:55:04 PM
Confirmed.

Quotes in command line arguments are not expanded in the same way in the RTL now used, so additional expansion was needed for switch -D, -I and -Fi used with -I"quoted text".

Wow so fast, this project has better support then hjwasm! :t
Nidud, may I request a feature?
Can you add to the listing file (/Fl), dump for all used procedure protos.
Example:

Code: [Select]
...
.NOLIST
Include kernel32.inc
...
.code

TestProc1 proc Par1:HANDLE,Par2:DWORD,Par3:PVOID
xor eax,eax
ret

TestProc1 endp

start:

invoke CreateFile,SADD('file.txt'),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
invoke TestProc1,eax,11111111h,NULL
invoke ExitProcess,0
end start

Listing file:
...
Procedures protos:

                N a m e                 PROTO

TestProc1  . . . . . . . . . . .        PROTO Par1:HANDLE, Par2:DWORD, Par3:PVOID
CreateFileA  . . . . . . . . . .        PROTO lpFileName:PSTR ,dwDesiredAccess:DWORD ,dwShareMode:DWORD ,lpSecurityAttributes:PVOID ,dwCreationDisposition:DWORD ,dwFlagsAndAttributes:DWORD ,hTemplateFile:HANDLE
ExitProcess  . . . . . . . . . .        PROTO uExitCode:DWORD
...

Where TestProc1 generated from source, CreateFileA & ExitProcess - just copy used proto from inc file.
Title: Re: Asmc source and binaries
Post by: nidud on January 17, 2017, 03:12:40 AM
Nidud, may I request a feature?
Can you add to the listing file (/Fl), dump for all used procedure protos.

Unused functions have a '*' added to the list if that helps:
Code: [Select]
.386
.model flat,stdcall
.code

foo proto
bar proto

foo()

END

Code: [Select]
Procedures, parameters and locals:

                N a m e                 Type     Value    Segment  Length

bar  . . . . . . . . . . . . . .        P Near32 00000000 No Seg   00000000 *External STDCALL
foo  . . . . . . . . . . . . . .        P Near32 00000000 No Seg   00000000 External  STDCALL
Title: Re: Asmc source and binaries
Post by: powershadow on January 17, 2017, 03:21:56 AM
Unused functions have a '*' added to the list if that helps:
Thanks for reply nidud, unfortunately it's not help :(. I need PROTOs
Title: Re: Asmc source and binaries
Post by: nidud on January 17, 2017, 03:48:16 AM
Well, I can see the usefulness of this and the information to compile the list may also be available, so I may look into this someday.
Title: Re: Asmc source and binaries
Post by: nidud on March 02, 2017, 08:08:18 AM
Some imort libraries are added to the source base. I was hoping to do this the simple way by target the .dll files directly, at least the 64-bit without any decoration.
Code: [Select]
32 libw /n /c /l /b /fac /ii version.lib %windir%\system32\version.dll
64 libw /n /c /l /b /fac /i6 version.lib %windir%\system32\version.dll

However, this didn't work very well for some (unknown) reason, so I ended up using .def files for all of them. The command that works looks like this:
Code: [Select]
++_BlockWOWIdle@4.'NTVDM.exe'

Given this works (I assume), the import record for the simple approach should in theory also work, at least for C and FASTCALL.

I have also done some testing with using windows.inc for differnt targets. The same include files should now work for both 32 and 64.bit, unicode/ascii, C/stdcall/fastcall, creating PE (no libs), using msvcrt (C/fastcall), or using the local library with startup modules.

Some changes have also been added to MAKE to simplify the build process. If %AsmcDir% is set MAKE will use the .\lib directory as a common include directory for .mif files.

Well, parsing these includes is tidious work so the current state looks like this:
Code: [Select]
WIN32_LEAN_AND_MEAN equ 1
include windows.inc

I currently only need kernel32 and user32 in the source base, but as the parsing improves more files will be added. Depending on how these functions are decleared, some will be defined with return type and line breaks, others with a single line:

Code: [Select]
if (_WIN32_WINNT GE 0x0500)
;BOOL
InitializeCriticalSectionAndSpinCount proto _CType \
     lpCriticalSection: LPCRITICAL_SECTION,
   dwSpinCount: DWORD
;DWORD
SetCriticalSectionSpinCount proto _CType \
     lpCriticalSection: LPCRITICAL_SECTION,
   dwSpinCount: DWORD
endif

Code: [Select]
ifndef _WDIRECT_DEFINED

;; also declared in direct.h

_wchdir proto :ptr wchar_t
_wgetcwd proto :ptr wchar_t, :SINT
_wgetdcwd proto :SINT, :ptr wchar_t, :SINT
_wmkdir proto :ptr wchar_t
_wrmdir proto :ptr wchar_t

_WDIRECT_DEFINED equ 1
endif
Title: Re: Asmc source and binaries
Post by: Vortex on March 03, 2017, 07:01:57 AM
Hi nidud,

Regarding 64-bit coding, it's easy to create .def files and import libraries from DLLs :

Creating include files and import libraries for ml64 (http://masm32.com/board/index.php?topic=5496.0)
Title: Re: Asmc source and binaries
Post by: nidud on March 03, 2017, 10:25:40 AM
Hey Vortex

The problem here is that LIBW (https://github.com/nidud/asmc/tree/master/source/linkw/libw) is capable of creating a working import record from the command line but fail to do so from a .dll file. Asmc also use the same code for the /pe switch. This means that the problem is fixable within the source for LIBW, but I haven't looked into this yet.

The include files used in the Asmc package is the same for both 32 and 64-bit, so I need the arguments for all the functions as well. In addition to this I also need the type and size of each of them as oppose to just flip from DWORD to QWORD.

It would have been possible to just flip :DWORD to :PTR in the MASM32 package as well as appose to create a new set of files, but having the correct size and types makes a huge difference with regards to debugging.

What I'm doing now is moving (and adding) declarations to the correct MS header files to get them better organized and thereby easier yo use for those more familiar with these. So there is a C/ASM merger of sorts going on here.

As for the decorated symbols for 32-bit they available here:
https://github.com/open-watcom/open-watcom-v2/tree/master/bld/w32api/lib

It's possible parse these to create simple .inc files for both 32 and 64-bit.
.def 32:
AddConsoleAliasA@12
.def 64:
AddConsoleAliasA
.inc 32/64
AddConsoleAliasA proto :ptr, :ptr, :ptr

This is currently how the imports are created.
32-bit:
https://github.com/nidud/asmc/blob/master/lib/makefile
64-bit:
https://github.com/nidud/asmc/blob/master/lib/x64/makefile

Given no libraries exist at this point and the .def files needs parsing, the parser is made using the includes with the /pe switch.
32-bit:
https://github.com/nidud/asmc/blob/master/lib/def/lbc.asm
64-bit:
https://github.com/nidud/asmc/blob/master/lib/def/lbc64.asm
Title: Re: Asmc source and binaries
Post by: nidud on March 04, 2017, 06:35:13 AM
A sample on how to use TCHAR.INC (https://github.com/nidud/asmc/blob/master/include/tchar.inc) for multiple targets. Most of the samples used by MS (https://msdn.microsoft.com/en-us/library/windows/desktop/aa364963(v=vs.85).aspx) apply this methood for unicode/ascii.
Code: [Select]
include stdio.inc
include stdlib.inc
include tchar.inc

.code

_tmain proc _CDecl argc:SINT, argv:PVOID

.for RSI = argv, edi = argc, ebx = 0: edi: edi--, ebx++, RSI += size_t

_tprintf("[%d]: %s\n", ebx, [RSI])
.endf
xor eax,eax
ret

_tmain endp

end _tstart

The command line for Asmc /pe:
asmc -pe -D__PE__ $*.asm
asmc -pe -ws -D_UNICODE -D__PE__ $*.asm
asmc -pe -D_WIN64 -D__PE__ $*.asm
asmc -pe -ws -D_UNICODE -D_WIN64 -D__PE__ $*.asm

The same code may also be built using the local library (https://github.com/nidud/asmc/tree/master/source/test/tchar), but only the 32-bit ASCII version has the appropriate startup module to handle the the main arguments for now.

Thus it may not be recommendable to mix 32 and 64-bit code in this way the possibility to do just that is at least within reach. The CALL directive is somewhat limited for this approach so you have to use INVOKE on function calls to handle the local/import declarations (_imp_*) correctly.

The startup module is now defined in the tchar.inc file for the /pe switch, so the _tstart macro is either <> or <mainCRTStartup>. The Rxx registers are define in up-case chars so they become case sensitive in 32-bit.
Title: Re: Asmc source and binaries
Post by: Vortex on March 04, 2017, 06:39:21 AM
Hi nidud,

I am fine with the DWORD to QWORD conversion but knowing the size and the type of the arguments is useful while debugging as you said.

The same include files supporting both 32-bit and 64-bit coding is a good idea. Creating the module definition files is not a problem, I do it with my lib2def tool. Pelle's library manager polib can be used for the same task.

Keep up the good work nidud :t
Title: Re: Asmc source and binaries
Post by: jj2007 on March 04, 2017, 07:06:06 AM
The same include files supporting both 32-bit and 64-bit coding is a good idea.

I agree, see 64-bit assembly with RichMasm (http://masm32.com/board/index.php?topic=5314.msg59884#msg59884). It is pretty easy, actually, mainly because Microsoft needs it for the transition from 32-bit to 64-bit ("The header files for the Windows API enable you to create 32- and 64-bit applications." (https://msdn.microsoft.com/en-us/library/windows/desktop/aa383745(v=vs.85).aspx)). My solution works fine, not a single extra library or header needed, but it is limited to the most important WinAPIs. Currently, I can't find enough enthusiasm to develop it further, simply because I don't see a convincing reason to go 64-bit 8)
Title: Re: Asmc source and binaries
Post by: nidud on March 11, 2017, 05:48:07 AM
Code: [Select]
WIN32_LEAN_AND_MEAN equ 1
include windows.inc

The rest of the include files are now added but not tested: no assembly error.
Title: Re: Asmc source and binaries
Post by: nidud on April 04, 2017, 03:02:50 AM
The Machine Architectures defined in windows.inc:
     _M_IX86      32-bit
     _M_AMD64   32/64-bit
     _M_IA64      64-bit

I added two directives: .amd64 and .win64. This to enable source level control as oppose to be depended on command line switches. I added this to simplify testing but I'm not sure how useful this will be elsewhere.

.win64 is the same as /win64 and .asm64 is equal to .x64.
I may add some options to the .win64 directive later.
.win64[: rsp | rbp | align | ...]

.win64 should be the first directive used since it needs to reset the assembler. The /win64 switch is similar to the /LARGEADDRESSAWARE switch, using "real" 64-bit.

Code: [Select]
.win64
.code

Code: [Select]
; Disassembly of file: win64.obj
; Mon Apr 03 18:46:46 2017
; Mode: 64 bits
; Syntax: MASM/ML64
; Instruction set: 8086, x64

Code: [Select]
.amd64
.model flat, fastcall
.code

Code: [Select]
; Disassembly of file: win64.obj
; Mon Apr 03 18:13:50 2017
; Mode: 32 bits
; Syntax: MASM/ML
; Instruction set: 80386

.386
.model flat
Title: Re: Asmc source and binaries
Post by: nidud on April 06, 2017, 11:57:33 PM
Quote
I may add some options to the .win64 directive later.
.win64[: rsp | rbp | align | ...]

I added the following syntax:

.WIN64 [: RSP | RBP | ALIGN | NOALIGN | SAVE | NOSAVE | AUTO | NOAUTO | FRAME | NOFRAME]

This may also be used with .X64 and .AMD64

RBP:
   STACKBASE = RBP
   FRAME = AUTO
   W64F_AUTOSTACKSP = 1
   W64F_SAVEREGPARAMS = 1
RSP:
   STACKBASE = RSP
   W64F_AUTOSTACKSP = 1
ALIGN:
   IF WIN64 == 0
      W64F_AUTOSTACKSP = 1
   W64F_STACKALIGN16 = 1
NOALIGN:
   W64F_STACKALIGN16 = 0
SAVE:
   W64F_SAVEREGPARAMS = 1
NOSAVE:
   W64F_SAVEREGPARAMS = 0
AUTO:
   W64F_AUTOSTACKSP = 1
NOAUTO:
   W64F_AUTOSTACKSP = 0
FRAME:
   FRAME = AUTO
NOFRAME:
   FRAME = NOAUTO

Code: [Select]
.win64: rbp align
.code

foo proc uses rdi a1:byte, a2:word, a3:dword, a4:qword

  local l1: byte,
l2: xmmword,
l3: byte,
l4: ymmword,
l5: byte

lea rax,l1
lea rax,l2
lea rax,l3
lea rax,l4
lea rax,l5

mov al,a1
mov ax,a2
mov eax,a3
mov rax,a4

ret
foo endp

Code: [Select]
00000000  48894C2408        *   mov [rsp+8], rcx
00000005  4889542410        *   mov [rsp+16], rdx
0000000A  4C89442418        *   mov [rsp+24], r8
0000000F  4C894C2420        *   mov [rsp+32], r9
00000014  55                *   push rbp
00000015  488BEC            *   mov rbp, rsp
00000018  57                *   push rdi
00000019  4881EC88000000    *   sub rsp, 104 + @ReservedStack
00000020  488D45F7              lea rax,l1
00000024  488D45E0              lea rax,l2
00000028  488D45DF              lea rax,l3
0000002C  488D45A0              lea rax,l4
00000030  488D459F              lea rax,l5

00000034  8A4510                mov al,a1
00000037  668B4518              mov ax,a2
0000003B  8B4520                mov eax,a3
0000003E  488B4528              mov rax,a4

00000042                        ret
00000042  4881C488000000    *   add rsp, 104 + @ReservedStack
00000049  5F                *   pop rdi
0000004A  C9                *   leave
0000004B  C3                *   retn

   .win64: rsp

Code: [Select]
00000000  57                *   push rdi
00000001  4881EC80000000    *   sub rsp, 96 + @ReservedStack
00000008  488D44247F            lea rax,l1
0000000D  488D442468            lea rax,l2
00000012  488D442467            lea rax,l3
00000017  488D442430            lea rax,l4
0000001C  488D44242F            lea rax,l5

00000021  8A842490000000        mov al,a1
00000028  668B842498000000      mov ax,a2
00000030  8B8424A0000000        mov eax,a3
00000037  488B8424A8000000      mov rax,a4
0000003F                        ret
0000003F  4881C480000000    *   add rsp, 96 + @ReservedStack
00000046  5F                *   pop rdi
00000047  C3                *   retn
Title: Re: Asmc source and binaries
Post by: Vortex on April 07, 2017, 05:28:31 AM
Hi nidud,

.win64:rbp align works fine, thanks :t

Code: [Select]
.win64:rbp align
option casemap:none

include    Window.inc

.data

ClassName  db "WndClass",0
AppName    db "Window",0

.code

start PROC

LOCAL hInstance:QWORD
   
    invoke  GetModuleHandle,0
    mov     hInstance,rax
   
    invoke  GetCommandLine
   
    invoke  WinMain,hInstance,0,rax,SW_SHOWDEFAULT
    invoke  ExitProcess,rax

start ENDP

WinMain PROC hInst:QWORD,hPrevInst:QWORD,CmdLine:QWORD,CmdShow:QWORD

    LOCAL   wc:WNDCLASSEX
    LOCAL   msg:MSG
    LOCAL   hwnd:QWORD

    mov     wc.cbSize,SIZEOF WNDCLASSEX
    mov     wc.style,CS_HREDRAW or CS_VREDRAW
    mov     rax,OFFSET WndProc
    mov     wc.lpfnWndProc,rax

    xor     rax,rax
    mov     wc.cbClsExtra,eax
    mov     wc.cbWndExtra,eax
    mov     wc.hInstance,rcx
    mov     wc.hbrBackground,COLOR_WINDOW+1
    mov     wc.lpszMenuName,rax

    lea     rax,ClassName
    mov     wc.lpszClassName,rax
    invoke  LoadIcon,0,IDI_APPLICATION
    mov     wc.hIcon,rax
    mov     wc.hIconSm,rax
    invoke  LoadCursor,0,IDC_ARROW
    mov     wc.hCursor,rax
    invoke  RegisterClassEx,ADDR wc

    mov     rax,CW_USEDEFAULT

    invoke  CreateWindowEx,0,ADDR ClassName,\
            ADDR AppName,\
            WS_OVERLAPPEDWINDOW,\
            rax,rax,rax,rax,0,0,\
            hInst,0

    mov     hwnd,rax

    invoke  ShowWindow,hwnd,SW_SHOWNORMAL
    invoke  UpdateWindow,hwnd

@@:
    invoke  GetMessage,ADDR msg,0,0,0
    test    rax,rax
    jz      @f
    invoke  TranslateMessage,ADDR msg
    invoke  DispatchMessage,ADDR msg
    jmp     @b
@@:
    mov     rax,msg.wParam
    ret

WinMain ENDP

WndProc PROC hWnd:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD

    cmp     edx,WM_DESTROY
    jne     @f

    invoke  PostQuitMessage,0
    jmp     _exit
@@:   
    invoke  DefWindowProc,hWnd,uMsg,wParam,lParam
    ret

_exit:

    xor     rax,rax
    ret

WndProc ENDP

END
Title: Re: Asmc source and binaries
Post by: nidud on April 07, 2017, 07:09:54 AM
Thanks for the sample Vortex  :t

I will try to use windows.inc and see how that goes..
Title: Re: Asmc source and binaries
Post by: nidud on April 07, 2017, 08:12:51 AM
Yep, that failed  :biggrin:

Updated winuser.inc (https://github.com/nidud/asmc/commit/99135b4e8ddb12249679b744059b41a817d2860a)..

New source: Note that align is only needed for xmm/ymmword locals.
Code: [Select]
include windows.inc

.win64: rbp
.code

start proc

    mov rbx,GetModuleHandle(0)
    ExitProcess(WinMain(rbx, 0, GetCommandLine(), SW_SHOWDEFAULT))

start endp

WinMain PROC hInstance: HINSTANCE,
hPrevInstance: HINSTANCE,
     lpCmdLine: LPSTR,
      nShowCmd: SINT

    LOCAL   wc:WNDCLASSEX
    LOCAL   msg:MSG
    LOCAL   hwnd:QWORD

    mov     wc.cbSize,SIZEOF WNDCLASSEX
    mov     wc.style,CS_HREDRAW or CS_VREDRAW
    mov     rax,OFFSET WndProc
    mov     wc.lpfnWndProc,rax

    xor     rax,rax
    mov     wc.cbClsExtra,eax
    mov     wc.cbWndExtra,eax
    mov     wc.hInstance,rcx
    mov     wc.hbrBackground,COLOR_WINDOW+1
    mov     wc.lpszMenuName,rax

    lea     rax,@CStr("WndClass")
    mov     wc.lpszClassName,rax
    mov     wc.hIcon,LoadIcon(0,IDI_APPLICATION)
    mov     wc.hIconSm,rax
    mov     wc.hCursor,LoadCursor(0,IDC_ARROW)
    RegisterClassEx(ADDR wc)

    mov     eax,CW_USEDEFAULT
    mov     hwnd,CreateWindowEx(0,"WndClass","Window",WS_OVERLAPPEDWINDOW,
eax,eax,eax,eax,0,0,hInstance,0)

    ShowWindow(hwnd,SW_SHOWNORMAL)
    UpdateWindow(hwnd)

    .while GetMessage(ADDR msg,0,0,0)

TranslateMessage(ADDR msg)
DispatchMessage(ADDR msg)
    .endw

    mov rax,msg.wParam
    ret

WinMain ENDP

WndProc PROC hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

    .if edx == WM_DESTROY

PostQuitMessage(0)
xor rax,rax
    .else
DefWindowProc(hWnd,uMsg,wParam,lParam)
    .endif
    ret

WndProc ENDP

END

The typing reduce the source with around 50 byte, however the linker increase the size of the exe to 4096.

Using rsp also works, but this extends the code a bit:
Code: [Select]
.win64: rsp save
00000208                    *   _TEXT ends
.win64: rbp
000001CF                    *   _TEXT ends
Title: Re: Asmc source and binaries
Post by: nidud on April 08, 2017, 01:43:00 AM
The Windows 64 ABI may seem complicated and messy, at least in assembly, but by using a standard stack-frame it basically behaves just like a STDCALL function.

There is however the possibility to simplify the mess as compilers do, but it becomes an open question then how far you have to stretch this before you end up compiling as oppose to just assemble the source. I tend to support the latter in this case, using the safe settings for all and apply manual optimization later.

The two normal optimization options are:
- if the function don't make any calls: skip the frame
- if the function can use the regs instead of the arguments: skip save.

Both of these could have been compiled I guess, but as for now this have to be done manually.

Example:

The last proc in the above sample may be optimized as follow:
Code: [Select]
.win64: rsp nosave

WndProc PROC hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

    .if edx == WM_DESTROY

PostQuitMessage(0)
xor rax,rax
    .else
DefWindowProc(rcx, edx, r8, r9)
    .endif
    ret

WndProc ENDP

Standard version:
Code: [Select]
WndProc PROC
        mov     qword ptr [rsp+8H], rcx                 ; 0185 _ 48: 89. 4C 24, 08
        mov     qword ptr [rsp+10H], rdx                ; 018A _ 48: 89. 54 24, 10
        mov     qword ptr [rsp+18H], r8                 ; 018F _ 4C: 89. 44 24, 18
        mov     qword ptr [rsp+20H], r9                 ; 0194 _ 4C: 89. 4C 24, 20
        push    rbp                                     ; 0199 _ 55
        mov     rbp, rsp                                ; 019A _ 48: 8B. EC
        sub     rsp, 32                                 ; 019D _ 48: 83. EC, 20
        cmp     edx, 2                                  ; 01A1 _ 83. FA, 02
        jnz     ?_003                                   ; 01A4 _ 75, 0F
        mov     ecx, 0                                  ; 01A6 _ B9, 00000000
        call    PostQuitMessage                         ; 01AB _ E8, 00000000(rel)
        xor     rax, rax                                ; 01B0 _ 48: 33. C0
        jmp     ?_004                                   ; 01B3 _ EB, 14

?_003:  mov     rcx, qword ptr [rbp+10H]                ; 01B5 _ 48: 8B. 4D, 10
        mov     edx, dword ptr [rbp+18H]                ; 01B9 _ 8B. 55, 18
        mov     r8, qword ptr [rbp+20H]                 ; 01BC _ 4C: 8B. 45, 20
        mov     r9, qword ptr [rbp+28H]                 ; 01C0 _ 4C: 8B. 4D, 28
        call    DefWindowProcA                          ; 01C4 _ E8, 00000000(rel)
?_004:  add     rsp, 32                                 ; 01C9 _ 48: 83. C4, 20
        leave                                           ; 01CD _ C9
        ret                                             ; 01CE _ C3
WndProc ENDP

Optimized version:
Code: [Select]
WndProc PROC
        sub     rsp, 40                                 ; 0185 _ 48: 83. EC, 28
        cmp     edx, 2                                  ; 0189 _ 83. FA, 02
        jnz     ?_003                                   ; 018C _ 75, 0F
        mov     ecx, 0                                  ; 018E _ B9, 00000000
        call    PostQuitMessage                         ; 0193 _ E8, 00000000(rel)
        xor     rax, rax                                ; 0198 _ 48: 33. C0
        jmp     ?_004                                   ; 019B _ EB, 05

?_003:  call    DefWindowProcA                          ; 019D _ E8, 00000000(rel)
?_004:  add     rsp, 40                                 ; 01A2 _ 48: 83. C4, 28
        ret                                             ; 01A6 _ C3
WndProc ENDP
Title: Re: Asmc source and binaries
Post by: nidud on June 06, 2017, 10:33:44 AM
Hi nidud,

Regarding 64-bit coding, it's easy to create .def files and import libraries from DLLs :

Creating include files and import libraries for ml64 (http://masm32.com/board/index.php?topic=5496.0)

Hi Vortex,

I tested Dll2definc.exe/def2lib64.exe but the LIB file only include 32-bit imports. The problem is that Dll2definc is a 32-bit EXE, so LoadLibrary() will load the 32-bit version of kernel32.dll.

Code: [Select]
include stdio.inc
include winnt.inc
include winbase.inc

.code

main proc argc:dword, argv:ptr
local dll
    .if argc == 2
mov esi,argv
.if LoadLibrary([esi+4])
    mov dll,eax
    mov edi,eax
    add edi,[eax+0x3C]
    mov edi,[edi].IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress
    add edi,eax
    mov ebx,[edi+0x18]
    mov esi,[edi+0x20]
    add esi,eax
    .while ebx
mov eax,[esi]
add eax,dll
printf("%s\n", eax)
add esi,4
dec ebx
    .endw
    FreeLibrary(dll)
.endif
    .endif
    xor eax,eax
    ret
main endp

    end

Some missing functions:
- RtlUnwindEx
- RtlVirtualUnwind

So here's a 64-bit version:
Code: [Select]
;
; Build: asmc -pe -D__PE__ -D_WIN64 dlldef.asm
;
include string.inc
include stdio.inc
include stdlib.inc
include winbase.inc
include tchar.inc

    .code

main proc
    .if rcx == 2
mov rdi,[rdx+8]
        .if LoadLibrary(rdi)
            mov r12,rax
            mov rbx,strcpy(strrchr(rdi,'.'),".def")
            .if fopen(rdi,"wt")
                mov r13,rax
                mov byte ptr [rbx],0
                fprintf(r13,"LIBRARY %s\nEXPORTS\n",rdi)
mov eax,[r12+0x3C]
mov eax,[r12+rax].IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress
mov ebx,[r12+rax+0x18]
mov esi,[r12+rax+0x20]
                add rsi,r12
                .while ebx
                    lodsd
    fprintf(r13,"\"%s\"\n",addr [rax+r12])
                    dec ebx
                .endw
                fclose(r13)
            .endif
            FreeLibrary(r12)
        .endif
    .else
        printf("\nUsage: DLLDEF <dllname>.dll\n\n")
    .endif
    xor eax,eax
    ret
main endp

    end _tstart

I only tested with kernel32 using def2lib64 and that seems to work.
Title: Re: Asmc source and binaries
Post by: Vortex on June 09, 2017, 03:57:31 AM
Hi nidud,

Thanks for your tests and the tool. My assumption considering that both of the 32-bit and 64-bit versions of a DLL are exporting the same functions was wrong.
Title: Re: Asmc source and binaries
Post by: nidud on June 09, 2017, 09:19:18 AM
My assumption considering that both of the 32-bit and 64-bit versions of a DLL are exporting the same functions was wrong.

I sort of assumed the same.

The problem here is that LIBW (https://github.com/nidud/asmc/tree/master/source/linkw/libw) is capable of creating a working import record from the command line but fail to do so from a .dll file. Asmc also use the same code for the /pe switch. This means that the problem is fixable within the source for LIBW, but I haven't looked into this yet.

Well, now we know why but the lib creation from the list produced works thought so no changes is needed there. I updated the makefiles for building the import libraries so that should work now.

https://github.com/nidud/asmc/blob/master/lib/
Title: Re: Asmc source and binaries
Post by: coder on June 15, 2017, 05:32:08 PM
The Windows 64 ABI may seem complicated and messy, at least in assembly, but by using a standard stack-frame it basically behaves just like a STDCALL function.
No, it is not. It looks messy because people don't have a clear understanding of the ABI itself. If you read the spec carefully, the ABI requires only 3 general criteria;

1. allocate shadow space
2. align the stack to 16 (everybody must ensure that this is done in their function bodies before calling out others)
3. XMMs for floating point, GPRs for integers (rcx,rdx...)

That's it. Everything else is not considered part of the ABI spec. For example, saving the volatile registers (rcx... r9) is never part of the ABI. It's up to the user's code whether to save them or not. YMM registers are not part of the ABI either. The code below shows your confusion in implementing the ABI. This my friend, indeed looks messy, because your're attempting to implement BOTH legacy STDCALL and FASTCALL on top of each other. It has nothing to do with optimized vs standard code.

Quote from: nidud
Standard version:
Code: [Select]
WndProc PROC
        mov     qword ptr [rsp+8H], rcx                 ; 0185 _ 48: 89. 4C 24, 08
        mov     qword ptr [rsp+10H], rdx                ; 018A _ 48: 89. 54 24, 10
        mov     qword ptr [rsp+18H], r8                 ; 018F _ 4C: 89. 44 24, 18   ;saving volatile registers part of the ABI?
        mov     qword ptr [rsp+20H], r9                 ; 0194 _ 4C: 89. 4C 24, 20
        push    rbp                                     ; 0199 _ 55                                   ;STDCALL?
        mov     rbp, rsp                                ; 019A _ 48: 8B. EC
        sub     rsp, 32                                 ; 019D _ 48: 83. EC, 20
        cmp     edx, 2                                  ; 01A1 _ 83. FA, 02
        jnz     ?_003                                   ; 01A4 _ 75, 0F
        mov     ecx, 0                                  ; 01A6 _ B9, 00000000
        call    PostQuitMessage                         ; 01AB _ E8, 00000000(rel)
        xor     rax, rax                                ; 01B0 _ 48: 33. C0
        jmp     ?_004                                   ; 01B3 _ EB, 14

?_003:  mov     rcx, qword ptr [rbp+10H]                ; 01B5 _ 48: 8B. 4D, 10
        mov     edx, dword ptr [rbp+18H]                ; 01B9 _ 8B. 55, 18
        mov     r8, qword ptr [rbp+20H]                 ; 01BC _ 4C: 8B. 45, 20
        mov     r9, qword ptr [rbp+28H]                 ; 01C0 _ 4C: 8B. 4D, 28
        call    DefWindowProcA                          ; 01C4 _ E8, 00000000(rel)
?_004:  add     rsp, 32                                 ; 01C9 _ 48: 83. C4, 20
        leave                                           ; 01CD _ C9
        ret                                             ; 01CE _ C3
WndProc ENDP

Title: Re: Asmc source and binaries
Post by: nidud on June 15, 2017, 10:05:53 PM
No, it is not. It looks messy because people don't have a clear understanding of the ABI itself. If you read the spec carefully, the ABI requires only 3 general criteria;

1. allocate shadow space

So the shadow space is part of the Application binary interface (https://en.wikipedia.org/wiki/Application_binary_interface) then.

Quote
For example, saving the volatile registers (rcx... r9) is never part of the ABI.

The first four integer or pointer parameters are passed in the rcx, rdx, r8, and r9 registers. The caller reserves space on the stack for arguments passed in registers. This is what the shadow space is used for.

https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/x64-architecture

Quote
The code below shows your confusion in implementing the ABI. This my friend, indeed looks messy, because your're attempting to implement BOTH legacy STDCALL and FASTCALL on top of each other. It has nothing to do with optimized vs standard code.

Yes, the ABI may look a bit complicated, messy and confusing in assembly.
Title: Re: Asmc source and binaries
Post by: coder on June 15, 2017, 11:16:40 PM
No, it is not. It looks messy because people don't have a clear understanding of the ABI itself. If you read the spec carefully, the ABI requires only 3 general criteria;

1. allocate shadow space

So the shadow space is part of the Application binary interface (https://en.wikipedia.org/wiki/Application_binary_interface) then.

Quote
For example, saving the volatile registers (rcx... r9) is never part of the ABI.

The first four integer or pointer parameters are passed in the rcx, rdx, r8, and r9 registers. The caller reserves space on the stack for arguments passed in registers. This is what the shadow space is used for.

https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/x64-architecture

Quote
The code below shows your confusion in implementing the ABI. This my friend, indeed looks messy, because your're attempting to implement BOTH legacy STDCALL and FASTCALL on top of each other. It has nothing to do with optimized vs standard code.

Yes, the ABI may look a bit complicated, messy and confusing in assembly.
I don't know. It's up to you to interpret my statements and suggestions. Maybe my terminologies are wrong, but your codes look funnier. If you think that stacking both fastcall and stdcall at the same entry point is a 'standard' code and practice, then enjoy it.

 
Title: Re: Asmc source and binaries
Post by: nidud on June 16, 2017, 12:33:15 AM
I don't know. It's up to you to interpret my statements and suggestions. Maybe my terminologies are wrong, but your codes look funnier.

Well, the sample you refer to is not "code" but the disassembled output from the object created by the assembler. The tool used is Agner Fog's objconv.exe.
Code: [Select]
Object file converter version 2.38 for x86 and x86-64 platforms.
Copyright (c) 2014 by Agner Fog. Gnu General Public License.

The original code was written by Vortext in Reply #28 (http://masm32.com/board/index.php?topic=5929.msg65018#msg65018), and I used this as a test case for the windows.inc project (https://github.com/nidud/asmc/tree/master/include) in Reply #30 (http://masm32.com/board/index.php?topic=5929.msg65021#msg65021).

Quote
If you think that stacking both fastcall and stdcall at the same entry point is a 'standard' code and practice, then enjoy it.

That may be confusing if your not familiar with the STDCALL calling convention. The 64-bit ABI is not "pure" FASTCALL but a combination of passing some arguments as registers and the rest on the stack. In addition to this stack is allocated (by the caller) for the arguments passed in registers.

The point of comparing STDCALL/FASTCALL has to do with the PROC and INVOKE directives and how this is handled by the assembler.

Code for Windows 32 ABI (stdcall)
Code: [Select]
WinMain PROC hInstance: HINSTANCE,
hPrevInstance: HINSTANCE,
     lpCmdLine: LPSTR,
      nShowCmd: SINT

strlen(lpCmdLine)

Code for Windows 64 ABI (fastcall)
Code: [Select]
WinMain PROC hInstance: HINSTANCE,
hPrevInstance: HINSTANCE,
     lpCmdLine: LPSTR,
      nShowCmd: SINT

strlen(lpCmdLine)

To see the code produced the object files are disassembled.
Title: Re: Asmc source and binaries
Post by: coder on June 16, 2017, 01:41:05 AM
I don't understand your point, Nidud. I questioned the validity of what you called as 'standard' vs 'optimized'. There's no way that the first output can be called a standard of any kind. Standard against what? Saving the volatile registers has never been part of any 64-bit ABI 'standard'. And you're wrong about the shadow space being used to save the volatile registers because it is not. It's the responsibility of the users / callers to save them, hence you don't see them in the second output. Do you see the second output making attempts to save RCX to R9? No. So do the Win64 APIs. They don't save the registers for you because it's not part of the ABI requirement. You, the callers, do it yourself. It's not "optimized". It's how it should be in a tight 64-bit ABI environment.

So it comes down to this;

Code: [Select]
;align the stack (this is requirement)
sub rsp,020h   ;---> this is requirement
mov [rsp],rcx  ;---> these are NOT.
...
...
mov [rsp+...],r9
call aWin64API  ;---> then you call the function. Not saving the volatile registers inside it.
Title: Re: Asmc source and binaries
Post by: nidud on June 16, 2017, 02:23:21 AM
I don't understand your point, Nidud.

The point is that this is not a help-desk for confused coders. If your confused (which you clearly are) about how the Windows 64 ABI works you should read up on the subject, ask Microsoft or post a question in the Campus.
Title: Re: Asmc source and binaries
Post by: coder on June 16, 2017, 02:38:32 AM
The first four integer or pointer parameters are passed in the rcx, rdx, r8, and r9 registers. The caller reserves space on the stack for arguments passed in registers. This is what the shadow space is used for.

https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/x64-architecture

No, simpleton. I am talking with proof! If you're smart, you don't listen to anything that MS tells you. You didn't read hard enough. The shadow space is indeed required but to put the volatile registers (rcx-r9) in there is optional, and in many occasions, it is used as a spill area for a functions own code, corrupting what you've put in there. Here's one example, one attempt to preserve r8, as per 'Microsoft recommendation';

Code: [Select]
externdef Sleep:proc
externdef printf:proc
option casemap:none

dseg segment page 'DATA'
  isr8 db 'R8 preserved? = %llX',0ah,0
dseg ends

cseg segment para 'CODE'
main proc
        sub     rsp,8     ;align stack (requirement)

        mov     r8,0CCh   ;we'll see about it

        sub     rsp,20h   ;allocate space (requirement)
        mov     [rsp],rcx
        mov     [rsp+8],rdx
        mov     [rsp+16],r8
        mov     [rsp+24],r9

        mov     rcx,500   ;integer argument (requirement)
        call    Sleep     ;call a WinAPI

        mov     rcx,[rsp]
        mov     rdx,[rsp+8]
        mov     r8,[rsp+16]
        mov     r9,[rsp+24]
        add     rsp,20h

        sub     rsp,20h
        mov     rdx,r8    ;is r8 preserved by Sleep
        mov     rcx,offset isr8
        call    printf
        add     rsp,28h   ;restore all

        ret

main endp
cseg ends
end

The output shows that R8 (RSP+16) is corrupted. Here's the output.
Code: [Select]
D:\MASM\MYCODE>ml64 /c prog.asm
Microsoft (R) Macro Assembler (x64) Version 14.10.25019.0
Copyright (C) Microsoft Corporation.  All rights reserved.

 Assembling: prog.asm

D:\MASM\MYCODE>gcc -m64 prog.obj -s -o prog.exe

D:\MASM\MYCODE>prog
R8 preserved? = 0

Title: Re: Asmc source and binaries
Post by: coder on June 16, 2017, 02:47:26 AM
I don't understand your point, Nidud.

The point is that this is not a help-desk for confused coders. If your confused (which you clearly are) about how the Windows 64 ABI works you should read up on the subject, ask Microsoft or post a question in the Campus.

One thing for sure, you're confusing the stack area for something else. Instead of dumping data there like everybody else do, you're stacking up two calling conventions there and call it "standard". Your "standard" is funny.

 

 
Title: Re: Asmc source and binaries
Post by: coder on June 19, 2017, 04:27:12 AM
Hi Nidud. I hope you're not offended in any way from what I said. Keep up the good work!
Title: Re: Asmc source and binaries
Post by: nidud on June 19, 2017, 05:36:31 AM

 :biggrin:

No problem coder but you may consider tone down your rhetoric a bit.

Do you understand now why the arguments passed in registers needs to be saved in WinMain() but not in WndProc() in the example above?
Title: Re: Asmc source and binaries
Post by: nidud on July 15, 2017, 01:00:24 AM
Here's another version of the dll-to-lib tools. This converts all dll-files in the system32 directory by default. There was more than 2000 files there (Win7-64).
Code: [Select]
SYSDLL creates import from %windir%/system32/[<mask>|*].dll

Usage: SYSDLL <options> [<mask>]

 /def - create .def files
 /lib - create .lib files
 /inc - create .inc files

Example:
Code: [Select]
ifdef __PE__
    .x64
    .model flat, fastcall
endif
include inc\msvcrt.inc

    .code

main proc

    .if fopen("test.asm", "rt")
        mov rsi,rax
        .if malloc(512)
            mov rdi,rax
            .while fgets(rdi, 512, rsi)
                printf(rdi)
            .endw
            free(rdi)
        .endif
        fclose(rsi)
    .endif
    exit(0)

main endp

    end main

Create library and include file (and directories):
Code: [Select]
SYSDLL /lib msvcrt
SYSDLL /inc msvcrt

Assemble:
Code: [Select]
asmc /win64 test.asm

inc\msvcrt.inc(1010) : error A2034: must be in segment block
 inc\msvcrt.inc(1010): Included by
  test.asm(11): Main line code
inc\msvcrt.inc(1014) : error A2034: must be in segment block
 inc\msvcrt.inc(1014): Included by
  test.asm(11): Main line code

Fixing the include file:
Code: [Select]
difftime proto :vararg
;div proto :vararg
exit proto :vararg
exp proto :vararg
expf proto :vararg
;fabs proto :vararg
fclose proto :vararg

Assemble and link:
Code: [Select]
asmc /win64 test.asm
linkw lib lib\msvcrt.lib file test.obj

Assemble and link:
Code: [Select]
asmc /pe /D__PE__ test.asm
Title: Re: Asmc source and binaries
Post by: nidud on October 07, 2017, 10:03:26 PM
Added __PE__ to the -pe switch

makefile (https://github.com/nidud/asmc/blob/master/source/test/windows/7/makefile)
Code: [Select]
#
#  __PE__ auto defined if switch -pe used
#
test.exe:
    asmc /q /pe $*.asm
    $@
    del $@
    asmc /q /pe /D_WIN64 $*.asm
    $@
    del $@

This build a 32 and 64-bit version of the Tutorial 16: Event Object (http://win32assembly.programminghorizon.com/tut16.html) sample.

Code: [Select]
include windows.inc
include winres.inc
ifdef _WIN64
option win64:3
APPNAME   equ <"Win64 ASM Event Example">
CLASSNAME equ <"Win64ASMEventClass">
else
rax equ <eax>
rbx equ <ebx>
rcx equ <ecx>
APPNAME   equ <"Win32 ASM Event Example">
CLASSNAME equ <"Win32ASMEventClass">
endif

IDM_START_THREAD    equ 1
IDM_STOP_THREAD     equ 2
IDM_EXIT            equ 3
IDR_MAINMENU        equ 30
WM_FINISH           equ WM_USER+100h

.data
EventStop   BOOL FALSE
hMenu       HANDLE ?
hwnd        HANDLE ?
hEventStart HANDLE ?
hThread     HANDLE ?
ThreadID    dd ?

.code

ThrdProc proc

    .while 1

        WaitForSingleObject(hEventStart, INFINITE)

        mov ecx,600000000

        .while ecx

            .if EventStop != TRUE

                add eax,eax
                dec ecx
            .else

                MessageBox(hwnd, "The thread is stopped",
                        "The calculation is completed!", MB_OK)

                mov EventStop,FALSE
                .continue(1)
            .endif
        .endw

        PostMessage(hwnd, WM_FINISH, 0, 0)
        EnableMenuItem(hMenu, IDM_START_THREAD, MF_ENABLED)
        EnableMenuItem(hMenu, IDM_STOP_THREAD, MF_GRAYED)
    .endw
    ret

ThrdProc endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

    .switch uMsg

      .case WM_DESTROY
        PostQuitMessage(NULL)
        xor eax,eax
        .endc

      .case WM_COMMAND

        .if !lParam ; menu commands

            movzx eax,word ptr wParam
            .switch eax

              .case IDM_START_THREAD
                SetEvent(hEventStart)
                EnableMenuItem(hMenu, IDM_START_THREAD, MF_GRAYED)
                EnableMenuItem(hMenu, IDM_STOP_THREAD, MF_ENABLED)
                .endc

              .case IDM_STOP_THREAD
                mov EventStop,TRUE
                EnableMenuItem(hMenu, IDM_START_THREAD, MF_ENABLED)
                EnableMenuItem(hMenu, IDM_STOP_THREAD, MF_GRAYED)
                .endc

              .case IDM_EXIT
                DestroyWindow(hWnd)
                .endc
            .endsw
        .endif
        xor eax,eax
        .endc

      .case WM_CREATE
        mov hEventStart,CreateEvent(NULL, FALSE, FALSE, NULL)
        mov hThread,CreateThread(NULL, NULL, &ThrdProc, NULL, NORMAL_PRIORITY_CLASS, &ThreadID)
        CloseHandle(hThread)
        xor eax,eax
        .endc

      .case WM_FINISH
        MessageBox(0, "The calculation is completed!", APPNAME, MB_OK)
        xor eax,eax
        .endc

      .default
        DefWindowProc(hWnd, uMsg, wParam, lParam)
    .endsw
    ret

WndProc endp

WinMain proc WINAPI hInst: HINSTANCE,
     hPrevInstance: HINSTANCE,
         lpCmdLine: LPSTR,
          nShowCmd: SINT

    local wc:WNDCLASSEX
    local msg:MSG

    mov wc.cbSize,SIZEOF WNDCLASSEX
    mov wc.style,CS_HREDRAW or CS_VREDRAW
    mov wc.lpfnWndProc,WndProc
    mov rcx,hInst
    xor eax,eax
    mov wc.cbClsExtra,eax
    mov wc.cbWndExtra,eax
    mov wc.hInstance,rcx
    mov wc.hbrBackground,COLOR_WINDOW
    mov wc.lpszMenuName,IDR_MAINMENU
ifdef _WIN64
    lea rax,@CStr("Win64ASMEventClass")
else
    lea rax,@CStr("Win32ASMEventClass")
endif
    mov wc.lpszClassName,rax
    mov wc.hIcon,LoadIcon(0, IDI_APPLICATION)
    mov wc.hIconSm,rax
    mov wc.hCursor,LoadCursor(0, IDC_ARROW)
    RegisterClassEx(&wc)

    mov hwnd,CreateWindowEx(WS_EX_CLIENTEDGE, CLASSNAME,
        APPNAME, WS_OVERLAPPEDWINDOW or WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT, 400, 200, 0, 0, hInst, 0)

    ShowWindow(hwnd, SW_SHOWNORMAL)
    UpdateWindow(hwnd)
    mov hMenu,GetMenu(hwnd)

    .while GetMessage(&msg, NULL, 0, 0)

        TranslateMessage(&msg)
        DispatchMessage(&msg)
    .endw
    mov rax,msg.wParam
    ret

WinMain endp

WinStart proc
    mov rbx,GetModuleHandle(0)
    ExitProcess(WinMain(rbx, 0, GetCommandLine(), SW_SHOWDEFAULT))
WinStart endp

RCBEGIN

    RCTYPES 1
    RCENTRY RT_MENU
    RCENUMN 1
    RCENUMX IDR_MAINMENU
    RCLANGX LANGID_US

    MENUBEGIN
      MENUNAME "&Thread", MF_END
        MENUITEM IDM_START_THREAD, "&Run Thread"
        MENUITEM IDM_STOP_THREAD,  "&Stop Thread"
        SEPARATOR
        MENUITEM IDM_EXIT, "E&xit", MF_END
    MENUEND

RCEND

    end WinStart

Some stats from the current source base:
Code: [Select]
2457 .ASM files - 194530 lines
 153 .INC files - 115220 lines
 276 .C   files - 121254 lines
 783 .LIB files
1425 macros
Title: Re: Asmc source and binaries
Post by: nidud on October 27, 2017, 01:23:18 AM
Some new updates.

Added a simple Hex editor to Doszip assigned to Ctrl-F4. In addition to the standard mode there is also a Class mode with the possibility to define a line-based struct of data. This may be a string or byte (hex) array, or integer value of size 1 to 8, signed/unsigned or hex.

Formatted struct's may be saved and loaded from disk at specific offsets.
Code: [Select]
00000068    PE···············································  CHAR[2]
0000006A    00006486                                           BYTE[4]
0000006E    0002                                               WORD(hexadecimal)
00000070    1509026722                                         DWORD(unsigned)
00000074    0                                                  DWORD(signed)
00000078    0                                                  DWORD(signed)
0000007C    00F0                                               WORD(hexadecimal)
0000007E    012F                                               WORD(hexadecimal)
00000080    0B02                                               BYTE[2]
00000082    5                                                  BYTE(signed)
00000083    1                                                  BYTE(signed)
00000084    512                                                DWORD(unsigned)
00000088    0                                                  DWORD(unsigned)
0000008C    0                                                  DWORD(unsigned)
00000090    4096                                               DWORD(unsigned)
00000094    4096                                               DWORD(unsigned)
00000098    0000000140000000                                   QWORD(hexadecimal)
000000A0    4096                                               DWORD(signed)
000000A4    512                                                DWORD(signed)
000000A8    4                                                  WORD(signed)
000000AA    0                                                  WORD(signed)
000000AC    0                                                  WORD(signed)
000000AE    0                                                  WORD(signed)
000000B0    4                                                  WORD(signed)
000000B2    0                                                  WORD(signed)
000000B4    0                                                  DWORD(signed)
000000B8    12288                                              DWORD(signed)
000000BC    512                                                DWORD(signed)
000000C0    0                                                  DWORD(signed)
000000C4    0003                                               WORD(hexadecimal)
000000C6    0000                                               WORD(hexadecimal)
000000C8    1048576                                            QWORD(unsigned)
000000D0    4096                                               QWORD(unsigned)
000000D8    1048576                                            QWORD(unsigned)

Added two switches to Asmc for using -pe.
-cui -- same as LINK /subsystem:console (default)
-gui -- same as LINK /subsystem:windows

This sets .Subsystem to IMAGE_SUBSYSTEM_WINDOWS_CUI or IMAGE_SUBSYSTEM_WINDOWS_GUI.

The combination of -pe -win64 will also set the .ImageBase to 0x140000000, default is 0x400000.

Asmc now adapts to ml64 if a simplified segment or a function prototype is found and no model or language defined. Additional [x|y]mm16..31 and zmm registers with a NASM-style {evex} prefix and implementation are also added.

This will now assemble to 64-bit fastcall:
Code: [Select]
    .code

    vaddps  xmm0,xmm1,[rax]     ; normal
    vpaddsb xmm0,xmm1,xmm2
    vcomisd xmm0,xmm1

    vaddps  xmm16,xmm1,[rax]    ; prefix
    vpaddsb xmm20,xmm0,xmm1
    vcomisd xmm0,xmm31

    {evex} vaddps  xmm0,xmm1,[rax]
    {evex} vpaddsb xmm0,xmm1,xmm2
    {evex} vcomisd xmm0,xmm1

    end

Code: [Select]
   0: c5 f0 58 00          vaddps xmm0,xmm1,XMMWORD PTR [rax]
   4: c5 f1 ec c2          vpaddsb xmm0,xmm1,xmm2
   8: c5 f9 2f c1          vcomisd xmm0,xmm1
   c: 62 e1 74 08 58 00    vaddps xmm16,xmm1,XMMWORD PTR [rax]
  12: 62 e1 7d 08 ec e1    vpaddsb xmm20,xmm0,xmm1
  18: 62 91 fd 08 2f c7    vcomisd xmm0,xmm31
  1e: 62 f1 74 08 58 00    vaddps xmm0,xmm1,XMMWORD PTR [rax]
  24: 62 f1 75 08 ec c2    vpaddsb xmm0,xmm1,xmm2
  2a: 62 f1 fd 08 2f c1    vcomisd xmm0,xmm1
Title: Re: Asmc source and binaries
Post by: nidud on November 13, 2017, 06:18:50 AM
Had a hardware meltdown here so now I have a cute little Fujitsu box installed. Well, been working on the AVX-512 implementation and finally get GitHup up and pushed the latest changes.

I wrote a lengthy test case (https://github.com/nidud/asmc/blob/master/source/asmc/regress/src/bin/avx_512.asm) for the implementation mostly taken from GAS and NASM. The binary output is bit-compatible with NASM and thus disassemble correctly with objdump.

There's not much code added for the implementation but it does however add a lot of instructions and inflate the tables. The hash tables is now increased but now all sizes are set to a power of two for convenience. Also, the reserved word table is now forced low-case to skip case testing on symbols. A simple benchmark of the 7000-lines test case compare to NASM:
Code: [Select]
   31 ClockTicks: asmc -q -bin a.asm
  156 ClockTicks: nasm n.asm

The math test compare to previous version:
Code: [Select]
3806 ClockTicks: asmc225.exe -q real_math.asm
3651 ClockTicks: \asmc\bin\asmc.exe -q real_math.asm
6287 ClockTicks: \jwasm\jwasm.exe -q real_math.asm

Added code:
312832 - version 2.25
333312 - version 2.26

A few types are added in addition to ZMMWORD:
Code: [Select]
8 16 32 64 128 256 512

1 2 4 8 10 16 32 64

AL AX EAX RAX XMM0 YMM0 ZMM0

  REAL10

REAL4 REAL8 REAL16 YMMWORD ZMMWORD

BYTE WORD DWORD QWORD OWORD YWORD ZWORD
Title: Re: Asmc source and binaries
Post by: nidud on November 16, 2017, 10:29:27 AM
Added public label::

A label is defined public if declared outside a procedure with a double colon. This simplify bear-bone  declarations, especially in 64-bit.

Code: [Select]
.code

public_label::

    nop
    ret

    end

Code: [Select]
; Mode: 64 bits
; Syntax: MASM/ML64
; Instruction set: 8086, x64

public public_label


_text   SEGMENT PARA 'CODE'                             ; section number 1

public_label PROC
        nop                                             ; 0000 _ 90
        ret                                             ; 0001 _ C3
public_label ENDP

_text   ENDS
Title: Re: Asmc source and binaries
Post by: Vortex on November 17, 2017, 06:09:38 AM
Hi nidud,

Sorry for the late reply. Testing sysdll :

Code: [Select]
sysdll.exe /def C:\WINDOWS\SysWOW64\msvcrt.dll

sysdll.exe /def C:\WINDOWS\System32\msvcrt.dll

sysdll.exe /inc C:\WINDOWS\SysWOW64\msvcrt.dll

sysdll.exe /inc C:\WINDOWS\System32\msvcrt.dll

sysdll.exe /lib C:\WINDOWS\SysWOW64\msvcrt.dll

sysdll.exe /lib C:\WINDOWS\System32\msvcrt.dll

I get three empty folders named def, inc and lib.  OS : Win XP 64-bit  Same problem on Win 7 64-bit
Title: Re: Asmc source and binaries
Post by: nidud on November 17, 2017, 06:32:35 AM
Looking at the source code (https://github.com/nidud/asmc/tree/master/source/tools/sysdll/sysdll.asm#L244) the wild arg seems to be the actual file name:
Code: [Select]
        sprintf(rdi, "%s\\system32\\%s.dll", rax, &wild)

This seems to work:

sysdll /inc msvcrt
sysdll /def msvcrt
sysdll /lib msvcrt

./def/msvcrt.def:
Code: [Select]
LIBRARY msvcrt
EXPORTS
"_CrtCheckMemory"
"_CrtDbgBreak"

./inc/msvcrt.inc:
Code: [Select]
includelib msvcrt.lib

_CrtCheckMemory proto :vararg
_CrtDbgBreak proto :vararg
_CrtDbgReport proto :vararg
Title: Re: Asmc source and binaries
Post by: Vortex on November 17, 2017, 06:58:34 AM
Hi nidud,

Thanks for the info. The tool works as you explained.
Title: Re: Asmc source and binaries
Post by: nidud on November 28, 2017, 02:59:20 AM
Did some cleanup in the GitHup source directory (https://github.com/nidud/asmc/tree/master/source) so some of the direct links posted may now fail. This was done to organize and improve the regression test for the libraries.

Wininc (https://github.com/nidud/asmc/tree/master/source/test/wininc) related source are now tested separately where most of the samples do not use libc and assembles with the -pe switch. Some more features are added both for LINKW and the include files to separate console/gui builds.

The -gui switch will now define __GUI__ and this will create a startup (https://github.com/nidud/asmc/blob/master/include/tchar.inc#L1009) calling [w]WinMain() as oppose to [w]main() in console mode. In addition to this the switch -ws now defines _UNICODE.

Some additional changes to Asmc:

Title: Re: Asmc source and binaries
Post by: nidud on December 06, 2017, 09:42:33 AM
Added some more support for invoking function pointers.

struct.funcptr(...)
[reg].struct.funcptr(...)
assume reg:ptr struct
[reg].funcptr(...)


Example (https://github.com/nidud/asmc/tree/master/source/test/wininc/D3D9):
Code: [Select]
;
; http://ube43.wix.com/directxers/apps/blog/directx-9-tutorial-1-ein-fenster
;

;; Every windows application needs to include this
include windows.inc
include tchar.inc

;; Every Direct3D application this
include d3d9.inc

.data
g_bContinue dd TRUE

.code


;; Besides the main function, there must be a message processing function
MsgProc proc WINAPI hWnd:HWND, msg:UINT, wParam:WPARAM, lParam:LPARAM

    .switch(msg)
      .case WM_DESTROY:
        PostQuitMessage( 0 )
        mov g_bContinue,FALSE
        .endc
      .default
        DefWindowProc( hWnd, msg, wParam, lParam )
    .endsw
    ret

MsgProc endp

;; The entry point of a windows application is the WinMain function
WinMain proc WINAPI uses rsi rdi rbx r12 hInstance:HINSTANCE, hPrevInstance:HINSTANCE, lpCmdLine:LPSTR, nShowCmd:SINT

    ;; Create a window class.
    local wc:WNDCLASSEX
    local hWnd:HWND
    ;local pD3D:LPDIRECT3D9
    local d3dpp:D3DPRESENT_PARAMETERS
    local pd3dDevice:LPDIRECT3DDEVICE9
    local msg:MSG

    xor eax,eax
    mov pd3dDevice,rax
    lea rdi,wc
    mov ecx,sizeof(WNDCLASSEX)
    rep stosb
    mov wc.cbSize,sizeof(WNDCLASSEX)
    mov wc.style,CS_CLASSDC
    lea rax,MsgProc
    mov wc.lpfnWndProc,rax
    lea rax,@CStr("Direct3D Window")
    mov wc.lpszClassName,rax
    mov wc.hInstance,GetModuleHandle(NULL)

    ;;Register the window class.
    RegisterClassEx( &wc );

    ;; Create the application's window.
    mov hWnd,CreateWindowEx(0, "Direct3D Window", "DirectXers - D3D9 Tutorial 1",
        WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, GetDesktopWindow(), NULL, wc.hInstance, NULL )

    ShowWindow(hWnd,SW_SHOW)

    .repeat

        ;; Create the Direct3D Object

        .if !Direct3DCreate9(D3D_SDK_VERSION)

            mov eax,E_FAIL
            .break
        .endif

        mov rbx,rax
        mov rdi,[rax]
        assume rdi: ptr IDirect3D9

        ;; Setup the device presentation parameters

        ZeroMemory( &d3dpp, sizeof(d3dpp) )
        mov d3dpp.Windowed,TRUE
        mov d3dpp.SwapEffect,D3DSWAPEFFECT_DISCARD
        mov d3dpp.BackBufferFormat,D3DFMT_UNKNOWN

        ;; The final step is to use the IDirect3D9::CreateDevice method to create the Direct3D device, as illustrated in the
        ;; following code example.

        .ifs [rdi].CreateDevice(rbx, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &pd3dDevice ) < 0

            MessageBox(hWnd, "No HAL HARDWARE_VERTEXPROCESSING! Sample will exit!", NULL, 0);
            [rdi].Release(rbx)
            mov eax,E_FAIL
            .break
        .endif

        mov rax,pd3dDevice
        mov rsi,[rax]
        mov r12,rax
        assume rsi: ptr IDirect3DDevice9

        .while ( g_bContinue )

            ;; Clear render region with blue
            [rsi].Clear( r12, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0, 0 )

            ;; before rendering something, you have to call this
            [rsi].BeginScene( r12 );

            ;;
            ;; rendering of scene objects happens her
            ;;

            ;; now end the scene
            [rsi].EndScene( r12 );

            ;; update screen = swap front and backbuffer
            [rsi].Present( r12, NULL, NULL, NULL, NULL)

            ;; A window has to handle its messages.
            TranslateMessage( &msg );
            DispatchMessage( &msg );
            PeekMessage(&msg, 0, 0, 0, PM_REMOVE)
        .endw

        ;; Do not forget to clean up here

        [rsi].Release( r12 );
        [rdi].Release( rbx )
        xor eax,eax
    .until 1
    ret

WinMain endp

    end _tstart

The C expansion of the interface class:
Code: [Select]
typedef struct IClassFactory
{
     const struct IClassFactoryVtbl FAR* lpVtbl;
} IClassFactory;

#define IDirect3D9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)

This means the current macro implementation (https://github.com/nidud/asmc/blob/master/include/d3d9.inc#L246) will not work in assembly. Not sure what or how to do this, maybe add a register:
Code: [Select]
IDirect3D9_QueryInterface macro p,a,b
mov rax,[p] ; assuming register
exitm<[rax].IDirect3D9.QueryInterface(p,a,b)>
endm

Well, the assembler will now handle the calls but the include files needs some update. The direct access as in the sample may also be simpler than using the macros but I need to do some more testing to see how it plays out.
Title: Re: Asmc source and binaries
Post by: nidud on December 09, 2017, 02:27:23 AM
Added direct usage of pointers and removed the macros. Using registers will still work as above but this seems to be simpler.
Code: [Select]
    p.QueryInterface(1, 2)

Expands to:
Code: [Select]
    mov     rcx, qword ptr [p]
    mov     rdx, 1           
    mov     r8, 2             
    mov     rax, qword ptr [rcx]
    call    qword ptr [rax]     

32-bit:
Code: [Select]
    push    2                 
    push    1                 
    push    dword ptr [_p]     
    mov     eax, dword ptr [_p]
    mov     eax, dword ptr [eax]
    call    dword ptr [eax]

Added d3dx9 include files and a few more examples. There seems to be a lot of these dll-files. The sample worked using d3dx9_40.dll so this is used as default import (assuming this is the version number).

The test samples was taken from this site:
http://ube43.wix.com/directxers/apps/blog/directx-9-tutorial-1-ein-fenster

Second sample using pointers:
Code: [Select]
;; Every windows application needs to include this
include windows.inc
include tchar.inc

;; Every Direct3D application this
include d3d9.inc
include d3dx9.inc

.data
g_lpEffect  LPD3DXEFFECT NULL
g_lpVertexBuffer LPDIRECT3DVERTEXBUFFER9 NULL
g_ShaderMatrix D3DXMATRIX <>
g_bContinue dd TRUE


;;Definition of the Vertex Format including position and diffuse color
D3DFVF_COLOREDVERTEX equ (D3DFVF_XYZ or D3DFVF_DIFFUSE)

COLORED_VERTEX STRUC
x           FLOAT ?     ;; Position
y           FLOAT ?
z           FLOAT ?
color       dd ?        ;; Color
COLORED_VERTEX ENDS

.code


;; Besides the main function, there must be a message processing function
MsgProc proc WINAPI hWnd:HWND, msg:UINT, wParam:WPARAM, lParam:LPARAM

    .switch(msg)
      .case WM_DESTROY:
        PostQuitMessage( 0 )
        mov g_bContinue,FALSE
        .endc
      .default
        DefWindowProc( hWnd, msg, wParam, lParam )
    .endsw
    ret

MsgProc endp

;; The entry point of a windows application is the WinMain function
WinMain proc WINAPI uses rdi hInstance:HINSTANCE, hPrevInstance:HINSTANCE, lpCmdLine:LPSTR, nShowCmd:SINT

    ;; Create a window class.
    local wc:WNDCLASSEX
    local hWnd:HWND
    local pD3D:LPDIRECT3D9
    local d3dpp:D3DPRESENT_PARAMETERS
    local pd3dDevice:LPDIRECT3DDEVICE9
    local msg:MSG
    local uiBufferSize:UINT
    local pVertices:ptr COLORED_VERTEX
    local uiPasses:UINT

    xor eax,eax
    mov pd3dDevice,rax
    lea rdi,wc
    mov ecx,sizeof(WNDCLASSEX)
    rep stosb
    mov wc.cbSize,sizeof(WNDCLASSEX)
    mov wc.style,CS_CLASSDC
    lea rax,MsgProc
    mov wc.lpfnWndProc,rax
    lea rax,@CStr("Direct3D Window")
    mov wc.lpszClassName,rax
    mov wc.hInstance,GetModuleHandle(NULL)

    ;;Register the window class.
    RegisterClassEx( &wc );

    ;; Create the application's window.
    mov hWnd,CreateWindowEx(0, "Direct3D Window", "DirectXers - D3D9 Tutorial 2",
        WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, GetDesktopWindow(), NULL, wc.hInstance, NULL )

    ShowWindow( hWnd, SW_SHOW )

    .repeat

        ;; Create the Direct3D Object

        .if !Direct3DCreate9( D3D_SDK_VERSION )

            mov eax,E_FAIL
            .break
        .endif
        mov pD3D,rax

        ;; Setup the device presentation parameters

        ZeroMemory( &d3dpp, sizeof(d3dpp) )
        mov d3dpp.Windowed,TRUE
        mov d3dpp.SwapEffect,D3DSWAPEFFECT_DISCARD
        mov d3dpp.BackBufferFormat,D3DFMT_UNKNOWN

        ;; The final step is to use the IDirect3D9::CreateDevice method to create the Direct3D device, as illustrated in the
        ;; following code example.

        .ifd pD3D.CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &pd3dDevice )

            MessageBox(hWnd, "No HAL HARDWARE_VERTEXPROCESSING! Sample will exit!", NULL, 0);
            pD3D.Release()
            mov eax,E_FAIL
            .break
        .endif

        ;; set the vertex buffer size 4 vertices * vertex structure size
        mov uiBufferSize,4*sizeof(COLORED_VERTEX)

        ;; create the buffer
        .ifd pd3dDevice.CreateVertexBuffer( uiBufferSize,
            D3DUSAGE_WRITEONLY, D3DFVF_COLOREDVERTEX, D3DPOOL_DEFAULT, &g_lpVertexBuffer, NULL )

            mov eax,E_FAIL
            .break
        .endif

        ;; lock the buffer for writing
        .ifd g_lpVertexBuffer._Lock( 0, uiBufferSize, &pVertices, 0 )

            mov eax,E_FAIL
            .break
        .endif

        ;; write the vertices. Here a simple rectangle
        mov rcx,pVertices
        assume rcx: ptr COLORED_VERTEX
        mov [rcx].x,-1.0    ;; left
        mov [rcx].y,-1.0    ;; bottom
        mov [rcx].z,0.0
        mov [rcx].color,0xffff0000  ;; red
        add rcx,COLORED_VERTEX
        mov [rcx].x,-1.0    ;; left
        mov [rcx].y,1.0     ;; top
        mov [rcx].z,0.0
        mov [rcx].color,0xff0000ff  ;; blue
        add rcx,COLORED_VERTEX
        mov [rcx].x,1.0     ;; right
        mov [rcx].y,-1.0    ;; bottom
        mov [rcx].z,0.0
        mov [rcx].color,0xff00ff00  ;; green
        add rcx,COLORED_VERTEX
        mov [rcx].x,1.0     ;; right
        mov [rcx].y,1.0     ;; top
        mov [rcx].z,0.0
        mov [rcx].color,0xffffffff  ;; white
        assume rcx: nothing

        ;; unlock the buffer
        g_lpVertexBuffer.Unlock()

        ;; set the Vertex Format
        pd3dDevice.SetFVF( D3DFVF_COLOREDVERTEX )

        ;; transfer the buffer to the gpu
        pd3dDevice.SetStreamSource( 0, g_lpVertexBuffer, 0, sizeof(COLORED_VERTEX) )

        ;; create an effect
        .ifd D3DXCreateEffectFromFile( pd3dDevice, "Effect.fx", NULL,
            NULL, D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY, NULL, &g_lpEffect, NULL )
            mov eax,E_FAIL
            .break
        .endif
        lea rcx,g_ShaderMatrix
        D3DXMatrixIdentity(rcx)
        g_lpEffect.SetMatrix( "ShaderMatrix", &g_ShaderMatrix )

        .while ( g_bContinue )

            ;; Clear render region with blue
            pd3dDevice.Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0, 0 )

            ;; before rendering something, you have to call this
            pd3dDevice.BeginScene()

            ;; rendering of scene objects happens her

            mov uiPasses,0
            g_lpEffect.Begin( &uiPasses, 0 )

            .for ( edi = 0: edi < uiPasses: edi++ )

                ;; render an effect pass
                g_lpEffect.BeginPass( edi )
                ;; render the rectangle
                pd3dDevice.DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 )
                g_lpEffect.EndPass()
            .endf

            g_lpEffect._End()

            ;; now end the scene
            pd3dDevice.EndScene()

            ;; update screen = swap front and backbuffer
            pd3dDevice.Present( NULL, NULL, NULL, NULL )

            ;; A window has to handle its messages.
            TranslateMessage( &msg );
            DispatchMessage( &msg );
            PeekMessage(&msg, 0, 0, 0, PM_REMOVE)
        .endw

        ;; Do not forget to clean up here

        pd3dDevice.Release()
        pD3D.Release()
        g_lpEffect.Release()
        g_lpVertexBuffer.Release()

        xor eax,eax
    .until 1
    ret

WinMain endp

    end _tstart
Title: Re: Asmc source and binaries
Post by: Vortex on December 10, 2017, 11:28:40 PM
Hi nidud,

I am trying to convert a COM example from Masm to the new Asmc syntax supporting the invocation of function pointers ( testing Asmc Version 2.27C ) :

Code: [Select]
.386
.model flat,stdcall
option casemap:none
option wstring:on

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\ole32.inc
include     SetWallpaper.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\ole32.lib

; LPActDesk TYPEDEF PTR IActiveDesktop

.data

CLSID_IActiveDesktop    GUID sCLSID_IActiveDesktop
IID_IActiveDesktop      GUID sIID_IActiveDesktop

DesktopImg dw 'test.bmp',0

.data?

wpo         WALLPAPEROPT <>
pAD         dd ?

.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
    mov         eax,pAD

    [eax].IActiveDesktop.SetWallpaper(ADDR 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

I get the following error message :

Code: [Select]
[eax].IActiveDesktop.SetWallpaper(ADDR DesktopImg,0)
Code: [Select]
SetWallpaper.asm(42) : error A2190: INVOKE requires prototype for procedure
Also as an alternative syntax, is it possible to use this expression with some modifications in the source code?

Code: [Select]
pAD.SetWallpaper(ADDR DesktopImg,0)
My intention is to preserve the definition of the IActiveDesktop interface like the following while using the new function pointer invocation syntax  :

Code: [Select]
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
Title: Re: Asmc source and binaries
Post by: nidud on December 14, 2017, 05:42:51 AM
I'v updated and added more include files using the STDMETHOD (https://github.com/nidud/asmc/blob/master/include/rpc.inc#L19) macro and added a SetWallpaper (https://github.com/nidud/asmc/tree/master/source/test/wininc/SetWallpaper) sample from the code above.
Code: [Select]
include windows.inc
include wininet.inc
include shlobj.inc

BITMAP0 equ <L"%SystemRoot%\\web\\wallpaper\\Windows\\img0.jpg">
BITMAP1 equ <L"%AsmcDir%\\source\\test\\wininc\\SetWallpaper\\test.bmp">

.data

CLSID_ActiveDesktop GUID _CLSID_ActiveDesktop
IID_IActiveDesktop  GUID _IID_IActiveDesktop

.code

main proc

  local w:WALLPAPEROPT
  local p:LPACTIVEDESKTOP

    CoInitialize(NULL)
    CoCreateInstance(&CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, &IID_IActiveDesktop, &p)
    p.SetWallpaper( BITMAP0, 0 )
    mov w.dwSize,sizeof(WALLPAPEROPT)
    mov w.dwStyle,WPSTYLE_CENTER
    p.SetWallpaperOptions( &w, 0 )
    p.ApplyChanges( AD_APPLY_ALL )
    p.Release()
    CoUninitialize()
    ret

main endp

    end

Also as an alternative syntax, is it possible to use this expression with some modifications in the source code?

Code: [Select]
pAD.SetWallpaper(ADDR DesktopImg,0)
My intention is to preserve the definition of the IActiveDesktop interface like the following while using the new function pointer invocation syntax  :

Code: [Select]
  local p:LPDIRECT3D9

    p.QueryInterface(1, 2)

*   invoke [rax].IDirect3D9.QueryInterface, p, 1, 2

The struct name is extracted from what the pointer points to and invoke needs a prototype so the functions needs to be defined.
Code: [Select]
IActiveDesktop STRUC

STDMETHOD QueryInterface, :REFIID, :ptr
STDMETHOD AddRef
STDMETHOD Release
STDMETHOD ApplyChanges, :DWORD
STDMETHOD GetWallpaper, :LPWSTR, :UINT, :DWORD
STDMETHOD SetWallpaper, :LPCWSTR, :DWORD
STDMETHOD GetWallpaperOptions, :LPWALLPAPEROPT, :DWORD
STDMETHOD SetWallpaperOptions, :LPCWALLPAPEROPT, :DWORD
STDMETHOD GetPattern, :LPWSTR, :UINT, :DWORD
Title: Re: Asmc source and binaries
Post by: Vortex on December 14, 2017, 05:55:11 AM
Hi nidud,

Thanks for the info and for the update :t 
Title: Re: Asmc source and binaries
Post by: nidud on December 17, 2017, 12:47:43 AM
Here's a PE COM-version using IShellFolder (https://github.com/nidud/asmc/tree/master/source/test/wininc/IShellFolder)
Code: [Select]
;
; https://msdn.microsoft.com/en-us/library/windows/desktop/bb762114(v=vs.85).aspx
;
include windows.inc
include wininet.inc
include shlobj.inc
include shlwapi.inc
include stdio.inc
include tchar.inc

.data
IID_IShellFolder  GUID _IID_IShellFolder

ifdef __PE__
GUID_NULL GUID <0>
IID_IOleDocument GUID _IID_IOleDocument
IID_IOleDocumentView GUID _IID_IOleDocumentView
IID_IOleDocumentSite GUID _IID_IOleDocumentSite
IID_IOleCommandTarget GUID _IID_IOleCommandTarget
IID_IExplorerPaneVisibility GUID _IID_IExplorerPaneVisibility
IID_IBandHost GUID _IID_IBandHost
IID_INameSpaceTreeControl GUID _IID_INameSpaceTreeControl
IID_INewMenuClient GUID _IID_INewMenuClient
IID_IEnumerableView GUID _IID_IEnumerableView
IID_IWebWizardExtension GUID _IID_IWebWizardExtension
IID_IWizardSite GUID _IID_IWizardSite
IID_IProfferService GUID _IID_IProfferService
IID_ICommDlgBrowser GUID _IID_ICommDlgBrowser
IID_IFolderView GUID _IID_IFolderView
IID_IShellTaskScheduler GUID _IID_IShellTaskScheduler
IID_IWebBrowserApp GUID _IID_IWebBrowserApp
IID_IProtectFocus GUID _IID_IProtectFocus
IID_IEnumOleDocumentViews GUID _IID_IEnumOleDocumentViews
endif

.code

main proc

  local psfParent:LPIShellFolder
  local pidlRelative:ptr PCUITEMID_CHILD
  local pidlItem:PIDLIST_ABSOLUTE
  local szDisplayName[MAX_PATH]:TCHAR
  local strret:STRRET

    mov pidlItem,ILCreateFromPath("C:\\")
    .ifd !SHBindToParent(pidlItem, &IID_IShellFolder, &psfParent, &pidlRelative)

psfParent.GetDisplayNameOf(pidlRelative, SHGDN_NORMAL, &strret)
psfParent.Release()
StrRetToBuf(&strret, pidlRelative, &szDisplayName, MAX_PATH)
printf("%s\n", &szDisplayName)
    .endif

    ILFree(pidlItem)
    xor eax,eax
    ret

main endp

    end _tstart
Title: Re: Asmc source and binaries
Post by: nidud on December 23, 2017, 08:02:27 AM
Some more COM stuff.

Code: [Select]
- added support for Class::Method proto
- added support for Class::Method proc
- added support for Class::Method(...)
- added support for com_ptr[Vtbl].proc_ptr(...)

Class::Method proto Class@Method proto :ptr Class

The conflict between Class and ClassVtbl.

I remove the Vtbl structs in the Windows include files to simplify declarations and usage. On creation of new classes this may however not be a good idea but still possible.

Normal C declaration:
Code: [Select]
ClassVtbl struct
   Method()
ClassVtbl ends

Class struct
   lpVtbl PClassVtbl ?
Class ends

Alternate declaration:
Code: [Select]
Class union
struct
   lpVtbl PClassVtbl ?
ends
struct
   Method()
ends
Class ends

The assembler will now search for ClassVtbl when pointers are expanded and use it if available. Expansion of p.Method() will in the latter be [rax].Class.Method and [rax].ClassVtbl.Method in the former.

Well, it's a very spesific word this «Vtbl», but the implementation was also spesific: to target the C implementation of a COM interface. This in turn dictates the general rules for usage.

Code: [Select]
METHOD macro entry, args:vararg
    local __type, __ptr
    ifnb <args>
        __type typedef proto :ptr, &args
    else
        __type typedef proto :ptr
    endif
    __ptr typedef ptr __type
    entry __ptr ?
    endm

Use Class::Class(Class*) as constructor
Code: [Select]
DEFINE_CLASS macro Class, args:vararg
    P&Class& typedef ptr Class
    P&Class&Vtbl typedef ptr &Class&Vtbl
    ifnb <args>
        exitm<&Class&::&Class& proto :P&Class&, &args>
    else
        exitm<&Class&::&Class& proto :P&Class&>
    endif
    endm

Code: [Select]
DEFINE_CLASS(TWindow)

TWindowVtbl struct
    METHOD  IsInsideX, :SINT
    METHOD  IsInsideY, :SINT
    METHOD  IsInsideXY, :SINT, :SINT
    METHOD  Release
TWindowVtbl ends

TWindow struct
    lpVtbl  PTWindowVtbl ?

    Flags   UINT ?
    Window  PCHAR_INFO ?
    rc     SMALL_RECT <>
TWindow ends

Code: [Select]
TWindow::IsInsideX proc x:SINT

    xor eax,eax
    .repeat

        .break .if dx > [rcx].rc.Right
        .break .if dx < [rcx].rc.Left

        mov eax,edx
        sub ax,[rcx].rc.Left
        inc eax

    .until 1
    ret

TWindow::IsInsideX endp

TWindow::IsInsideXY proc x:SINT, y:SINT

    .if TWindow::IsInsideX(rcx, edx)
        TWindow::IsInsideY(rcx, r8d)
    .endif
    ret

TWindow::IsInsideXY endp
Title: Re: Asmc source and binaries
Post by: AssemblyChallenge on January 06, 2018, 12:55:32 AM
Hi nidud.

I have been following your great work with Asmc. One thing I would like to see from your project is some sort of page and/or manual, something like the one from Uasm's guys.

The info included in Git/Readme, for example, is very short IMHO. In the first page of this post someone asked "What is Asmc?" and then you replied with some features (handling of strings, .SWITCH, etc). Could you please create some sort of PDF with all the details? I was tempted to simply copy/paste that post in a file but it would be -probably- incomplete as Asmc has a lot more under the hood.

Regards.
Title: Re: Asmc source and binaries
Post by: nidud on January 06, 2018, 02:13:13 AM
The text you refer to is taken from the Asmc help file included in the package. In addition to this there are a few thousand ASM-files with test cases and samples including all extensions and features of the assembler.
Title: Re: Asmc source and binaries
Post by: AssemblyChallenge on January 06, 2018, 03:05:40 AM
Let me spare some time -and embarrassment- to the newcomers of Asmc. The help file is located at:

asmc-master\source\asmc\asmc.chm

Thank you, I was looking everywhere... except in the source code :icon_redface:
Title: Re: Asmc source and binaries
Post by: AssemblyChallenge on January 12, 2018, 06:35:21 AM
Hi Nidud.

After my adventures while trying Asmc and the cvpack.exe building error, maybe you should include that file in Asmc's tree, or perhaps explain in the help file that you must download it from Jwasm's site. I got this tip from good friend Ramon.

Regards.

PD: In my next project I will be using your compiler.
Title: Re: Asmc source and binaries
Post by: nidud on March 25, 2018, 04:23:49 AM
After my adventures while trying Asmc and the cvpack.exe building error, maybe you should include that file in Asmc's tree, or perhaps explain in the help file that you must download it from Jwasm's site.

This is a Microsoft executable. Think there are a few clones included in the Open Watcom package.

Quote
PD: In my next project I will be using your compiler.

 :t
Title: Re: Asmc source and binaries
Post by: nidud on March 25, 2018, 05:11:27 AM
A few new changes.

- convert MOV REG,0 to XOR for args.
- some unnecessary stack adjustments was removed in 64-bit if LEAVE used.
- added use of PROC in struct member declarations.
- added .classdef directive.
- added .ends directive
- added .pragma directive

Code: [Select]
.classdef Class

    Read proc :ptr, :ptr, :ptr

    .ends

foo proc

  local d:Class

    d.Read(0,0,1)
    ret

foo endp

Code: [Select]
   0: 55                    push   rbp
   1: 48 8b ec              mov    rbp,rsp
   4: 48 83 ec 30          sub    rsp,0x30
   8: 48 8d 4d f8          lea    rcx,[rbp-0x8]
   c: 48 33 d2              xor    rdx,rdx
   f: 4d 33 c0              xor    r8,r8
  12: 49 c7 c1 01 00 00 00 mov    r9,0x1
  19: 48 8b 01              mov    rax,QWORD PTR [rcx]
  1c: ff 50 08              call   QWORD PTR [rax+0x8]
  1f: c9                    leave 
  20: c3                    ret   

Test case for .classdef and .pragma:
https://github.com/nidud/asmc/tree/master/source/test/classdef/0

User registers prohibit this optimization but the -Cs switch will fix that.
Code: [Select]
foo proc uses rsi rdi
Code: [Select]
   0: 55                    push   rbp
   1: 48 8b ec              mov    rbp,rsp
   4: 56                    push   rsi
   5: 57                    push   rdi
   6: 48 83 ec 30          sub    rsp,0x30
   a: 48 8d 4d e8          lea    rcx,[rbp-0x18]
   e: 48 33 d2              xor    rdx,rdx
  11: 4d 33 c0              xor    r8,r8
  14: 49 c7 c1 01 00 00 00 mov    r9,0x1
  1b: 48 8b 01              mov    rax,QWORD PTR [rcx]
  1e: ff 50 08              call   QWORD PTR [rax+0x8]
  21: 48 83 c4 30          add    rsp,0x30
  25: 5f                    pop    rdi
  26: 5e                    pop    rsi
  27: c9                    leave 
  28: c3                    ret   

Using -Cs
Code: [Select]
   0: 56                    push   rsi
   1: 57                    push   rdi
   2: 55                    push   rbp
   3: 48 8b ec              mov    rbp,rsp
   6: 48 83 ec 30          sub    rsp,0x30
   a: 48 8d 4d f8          lea    rcx,[rbp-0x8]
   e: 48 33 d2              xor    rdx,rdx
  11: 4d 33 c0              xor    r8,r8
  14: 49 c7 c1 01 00 00 00 mov    r9,0x1
  1b: 48 8b 01              mov    rax,QWORD PTR [rcx]
  1e: ff 50 08              call   QWORD PTR [rax+0x8]
  21: c9                    leave 
  22: 5f                    pop    rdi
  23: 5e                    pop    rsi
  24: c3                    ret   
Title: Re: Asmc source and binaries
Post by: nidud on April 07, 2018, 02:39:27 AM
Added more include files (https://github.com/nidud/asmc/tree/master/include) for D3D10/11.

A simple test case (https://github.com/nidud/asmc/tree/master/source/test/wininc/D3D11/1) for D3D11CreateDevice (https://msdn.microsoft.com/en-us/library/windows/desktop/ff476082(v=vs.85).aspx)():
Code: [Select]
include windows.inc
include SpecStrings.inc
include d3d11.inc
include tchar.inc

    .code

MsgProc proc WINAPI hWnd:HWND, msg:UINT, wParam:WPARAM, lParam:LPARAM

    .switch(msg)
      .case WM_DESTROY:
        PostQuitMessage( 0 )
        .endc
      .default
        DefWindowProc( hWnd, msg, wParam, lParam )
    .endsw
    ret

MsgProc endp

WinMain proc WINAPI uses rdi hInstance:HINSTANCE, hPrevInstance:HINSTANCE, lpCmdLine:LPSTR, nShowCmd:SINT

    local wc:WNDCLASSEX
    local hWnd:HWND
    local msg:MSG

    local createDeviceFlags:UINT
    local featureLevel:D3D_FEATURE_LEVEL
    local device:ptr ID3D11Device
    local context:ptr ID3D11DeviceContext

    xor eax,eax
    lea rdi,wc
    mov ecx,sizeof(WNDCLASSEX)
    rep stosb
    mov wc.cbSize,sizeof(WNDCLASSEX)
    mov wc.style,CS_CLASSDC
    lea rax,MsgProc
    mov wc.lpfnWndProc,rax
    lea rax,@CStr("Direct3D Window")
    mov wc.lpszClassName,rax
    mov wc.hInstance,GetModuleHandle(NULL)
    RegisterClassEx( &wc )
    mov hWnd,CreateWindowEx(0, "Direct3D Window", "D3D11 Test 1",
        WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, GetDesktopWindow(), NULL, wc.hInstance, NULL )
    ShowWindow( hWnd, SW_SHOW )

    .repeat

        mov createDeviceFlags,0
ifdef _DEBUG
        mov createDeviceFlags,D3D11_CREATE_DEVICE_DEBUG
endif
        .ifd D3D11CreateDevice(
                0,
                D3D_DRIVER_TYPE_HARDWARE,
                0,
                createDeviceFlags,
                0,
                0,
                D3D11_SDK_VERSION,
                &device,
                &featureLevel,
                &context) != S_OK

            MessageBox(0, "D3D11CreateDevice Failed.", "D3D11 Test 1", 0)
            mov eax,E_FAIL
            .break
        .else
            device.Release()
            MessageBox(0, "D3D11CreateDevice Success.", "D3D11 Test 1", 0)
        .endif
        xor eax,eax
    .until 1
    ret

WinMain endp

    end _tstart
Title: Re: Asmc source and binaries
Post by: nidud on April 08, 2018, 10:25:27 PM
Added two more samples from the Direct3D-Tutorial-Win32 package. The default build for these samples are 64-bit. To build a 32-bit version just remove the -win64 switch from the makefile.

The tutorial can be downloaded from here:
https://code.msdn.microsoft.com/windowsdesktop/Direct3D-Tutorial-Win32-829979ef

The first sample is a Unicode build demonstrating the basic setup of a Direct3D 11 device.
Code: [Select]
;;--------------------------------------------------------------------------------------
;; File: Tutorial01.cpp
;;
;; This application demonstrates creating a Direct3D 11 device
;;
;; http://msdn.microsoft.com/en-us/library/windows/apps/ff729718.aspx
;;
;; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
;; ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
;; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
;; PARTICULAR PURPOSE.
;;
;; Copyright (c) Microsoft Corporation. All rights reserved.
;;--------------------------------------------------------------------------------------

include windows.inc
include SpecStrings.inc
include d3d11_1.inc
include gdipluscolor.inc
include tchar.inc
ifndef _WIN64
    .686
    .xmm
endif

    .data
;;--------------------------------------------------------------------------------------
;; Global Variables
;;--------------------------------------------------------------------------------------
g_hInst HINSTANCE NULL
g_hWnd HWND NULL
g_driverType D3D_DRIVER_TYPE D3D_DRIVER_TYPE_NULL
g_featureLevel D3D_FEATURE_LEVEL D3D_FEATURE_LEVEL_11_0
g_pd3dDevice LPID3D11Device NULL
g_pd3dDevice1 LPID3D11Device1 NULL
g_pImmediateContext LPID3D11DeviceContext NULL
g_pImmediateContext1 LPID3D11DeviceContext1 NULL
g_pSwapChain LPIDXGISwapChain NULL
g_pSwapChain1 LPIDXGISwapChain1 NULL
g_pRenderTargetView LPID3D11RenderTargetView NULL

IID_IDXGIFactory1 GUID _IID_IDXGIFactory1
IID_IDXGIDevice GUID _IID_IDXGIDevice
IID_IDXGIFactory2 GUID _IID_IDXGIFactory2
IID_ID3D11Device1 GUID _IID_ID3D11Device1
IID_ID3D11DeviceContext1 GUID _IID_ID3D11DeviceContext1
IID_IDXGISwapChain GUID _IID_IDXGISwapChain
IID_ID3D11Texture2D GUID _IID_ID3D11Texture2D

    .code
;;--------------------------------------------------------------------------------------
;; Forward declarations
;;--------------------------------------------------------------------------------------
ifdef __PE__
option dllimport:none
endif
InitWindow proto :HINSTANCE, :SINT
InitDevice proto
CleanupDevice proto
WndProc proto :HWND, :UINT, :WPARAM, :LPARAM
Render proto

;;--------------------------------------------------------------------------------------
;; Entry point to the program. Initializes everything and goes into a message processing
;; loop. Idle time is used to render the scene.
;;--------------------------------------------------------------------------------------
wWinMain proc WINAPI hInstance:HINSTANCE, hPrevInstance:HINSTANCE, lpCmdLine:LPWSTR, nCmdShow:SINT

    local msg:MSG

    .repeat

.ifd InitWindow( hInstance, nCmdShow ) != S_OK

    xor eax,eax
    .break
.endif

.ifd InitDevice() != S_OK

    CleanupDevice()
    xor eax,eax
    .break
.endif

;; Main message loop
mov msg.message,0
.while( msg.message != WM_QUIT )

    .ifd PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )

TranslateMessage( &msg )
DispatchMessage( &msg )
    .else
Render()
    .endif
.endw

CleanupDevice()
mov rax,msg.wParam

    .until 1
    ret

wWinMain endp

;;--------------------------------------------------------------------------------------
;; Register class and create window
;;--------------------------------------------------------------------------------------
InitWindow proc uses rsi rdi hInstance:HINSTANCE, nCmdShow:SINT

    local wcex:WNDCLASSEX
    local rc:RECT

    ;; Register class
    mov wcex.cbSize,sizeof( WNDCLASSEX )
    mov wcex.style,CS_HREDRAW or CS_VREDRAW
    lea rax,WndProc
    mov wcex.lpfnWndProc,rax
    mov wcex.cbClsExtra,0
    mov wcex.cbWndExtra,0
    mov rax,hInstance
    mov wcex.hInstance,rax
    mov wcex.hIcon,LoadIcon( hInstance, IDI_APPLICATION )
    mov wcex.hIconSm,rax
    mov wcex.hCursor,LoadCursor( NULL, IDC_ARROW )
    mov wcex.hbrBackground,COLOR_WINDOW + 1
    mov wcex.lpszMenuName,NULL
    lea rax,@CStr("TutorialWindowClass")
    mov wcex.lpszClassName,rax

    .repeat

.if !RegisterClassEx( &wcex )

    mov eax,E_FAIL
    .break
.endif

;; Create window
mov rax,hInstance
mov g_hInst,rax

mov rc.left,0
mov rc.top,0
mov rc.right,800
mov rc.bottom,600

AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE )

mov esi,rc.right
sub esi,rc.left
mov edi,rc.bottom
sub edi,rc.top

.if CreateWindow("TutorialWindowClass", "Direct3D 11 Tutorial 1: Direct3D 11 Basics",
WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, esi, edi, NULL, NULL, hInstance, NULL)

    mov g_hWnd,rax
    ShowWindow( rax, nCmdShow )
    mov eax,S_OK
.else
    mov eax,E_FAIL
.endif
    .until 1
    ret

InitWindow endp

;;--------------------------------------------------------------------------------------
;; Called every time the application receives a message
;;--------------------------------------------------------------------------------------
WndProc proc hWnd:HWND, message:UINT, wParam:WPARAM, lParam:LPARAM

    local ps:PAINTSTRUCT
    local hdc:HDC

    .repeat

.switch( message )
.case WM_PAINT
    mov hdc,BeginPaint( hWnd, &ps )
    EndPaint( hWnd, &ps )
    .endc

.case WM_DESTROY
    PostQuitMessage( 0 )
    .endc

    ;; Note that this tutorial does not handle resizing (WM_SIZE) requests,
    ;; so we created the window without the resize border.

.default
    DefWindowProc( hWnd, message, wParam, lParam )
    .break
.endsw
xor eax,eax
    .until 1
    ret

WndProc endp

;;--------------------------------------------------------------------------------------
;; Create Direct3D device and swap chain
;;--------------------------------------------------------------------------------------
InitDevice proc uses rsi rdi rbx

    local hr:HRESULT
    local rc:RECT
    local _width:UINT
    local height:UINT
    local vp:D3D11_VIEWPORT
    local numFeatureLevels:UINT
    local numDriverTypes:UINT
    local driverTypes[3]:D3D_DRIVER_TYPE
    local featureLevels[4]:D3D_FEATURE_LEVEL
    local dxgiFactory:LPIDXGIFactory1
    local dxgiDevice:LPIDXGIDevice
    local pBackBuffer:ptr ID3D11Texture2D
    local adapter:ptr IDXGIAdapter
    local dxgiFactory2:ptr IDXGIFactory2
    local sd:DXGI_SWAP_CHAIN_DESC1
    local sd2:DXGI_SWAP_CHAIN_DESC
    local createDeviceFlags:UINT

    GetClientRect( g_hWnd, &rc )

    mov eax,rc.right
    sub eax,rc.left
    mov _width,eax
    mov eax,rc.bottom
    sub eax,rc.top
    mov height,eax

    mov createDeviceFlags,0
ifdef _DEBUG
    mov createDeviceFlags,D3D11_CREATE_DEVICE_DEBUG
endif

    mov driverTypes[0],D3D_DRIVER_TYPE_HARDWARE
    mov driverTypes[4],D3D_DRIVER_TYPE_WARP
    mov driverTypes[8],D3D_DRIVER_TYPE_REFERENCE
    mov numDriverTypes,3;ARRAYSIZE( driverTypes )

    mov featureLevels[0],D3D_FEATURE_LEVEL_11_1
    mov featureLevels[4],D3D_FEATURE_LEVEL_11_0
    mov featureLevels[8],D3D_FEATURE_LEVEL_10_1
    mov featureLevels[12],D3D_FEATURE_LEVEL_10_0
    mov numFeatureLevels,4;ARRAYSIZE( featureLevels )

    .for( ebx = 0: ebx < numDriverTypes: ebx++ )

lea rsi,driverTypes
mov eax,[rsi+rbx*4]
mov g_driverType,eax

.ifd D3D11CreateDevice(
NULL,
g_driverType,
NULL,
createDeviceFlags,
&featureLevels,
numFeatureLevels,
D3D11_SDK_VERSION,
&g_pd3dDevice,
&g_featureLevel,
&g_pImmediateContext ) == E_INVALIDARG

    ;; DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1
    ;; so we need to retry without it
    mov edi,numFeatureLevels
    dec edi
    lea rsi,featureLevels
    add rsi,4

    D3D11CreateDevice(
NULL,
g_driverType,
NULL,
createDeviceFlags,
rsi,
edi,
D3D11_SDK_VERSION,
&g_pd3dDevice,
&g_featureLevel,
&g_pImmediateContext )
.endif

.break .if eax == S_OK
    .endf

    .repeat

.break .if eax != S_OK

;; Obtain DXGI factory from device (since we used nullptr for pAdapter above)
mov dxgiFactory,NULL
mov dxgiDevice,NULL

.ifd g_pd3dDevice.QueryInterface(
    &IID_IDXGIDevice,
    &dxgiDevice ) == S_OK

    mov hr,eax
    mov adapter,NULL
    .ifd dxgiDevice.GetAdapter(&adapter) == S_OK

adapter._GetParent( &IID_IDXGIFactory1, &dxgiFactory )
mov hr,eax
adapter.Release()
    .endif
    dxgiDevice.Release()
.else
    mov hr,eax
.endif
mov eax,hr
.break .if eax != S_OK

;; Create swap chain
mov dxgiFactory2,NULL
dxgiFactory.QueryInterface( &IID_IDXGIFactory2, &dxgiFactory2 )
mov hr,eax
.if ( dxgiFactory2 )

    ;; DirectX 11.1 or later
    g_pd3dDevice.QueryInterface( &IID_ID3D11Device1, &g_pd3dDevice1 )
    mov hr,eax
    .if eax == S_OK

g_pImmediateContext.QueryInterface( &IID_ID3D11DeviceContext1, &g_pImmediateContext1 )
    .endif

    ZeroMemory(&sd, sizeof(sd))
    mov eax,_width
    mov sd._Width,eax
    mov eax,height
    mov sd.Height,eax
    mov sd.Format,DXGI_FORMAT_R8G8B8A8_UNORM
    mov sd.SampleDesc.Count,1
    mov sd.SampleDesc.Quality,0
    mov sd.BufferUsage,DXGI_USAGE_RENDER_TARGET_OUTPUT
    mov sd.BufferCount,1

    dxgiFactory2.CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, NULL, NULL, &g_pSwapChain1 )
    mov hr,eax
    .if eax == S_OK

g_pSwapChain1.QueryInterface( &IID_IDXGISwapChain, &g_pSwapChain )
    .endif

    dxgiFactory2.Release()

.else

    ;; DirectX 11.0 systems

    ZeroMemory(&sd2, sizeof(sd2))
    mov sd2.BufferCount,1
    mov eax,_width
    mov sd2.BufferDesc._Width,eax
    mov eax,height
    mov sd2.BufferDesc.Height,eax
    mov sd2.BufferDesc.Format,DXGI_FORMAT_R8G8B8A8_UNORM
    mov sd2.BufferDesc.RefreshRate.Numerator,60
    mov sd2.BufferDesc.RefreshRate.Denominator,1
    mov sd2.BufferUsage,DXGI_USAGE_RENDER_TARGET_OUTPUT
    mov rax,g_hWnd
    mov sd2.OutputWindow,rax
    mov sd2.SampleDesc.Count,1
    mov sd2.SampleDesc.Quality,0
    mov sd2.Windowed,TRUE

    dxgiFactory.CreateSwapChain( g_pd3dDevice, &sd2, &g_pSwapChain )
    mov hr,eax
.endif

;; Note this tutorial doesn't handle full-screen swapchains so we block
;; the ALT+ENTER shortcut
dxgiFactory.MakeWindowAssociation( g_hWnd, DXGI_MWA_NO_ALT_ENTER )
dxgiFactory.Release()

mov eax,hr
.break .if eax != S_OK

;; Create a render target view
mov pBackBuffer,NULL
.break .ifd g_pSwapChain.GetBuffer(0, &IID_ID3D11Texture2D, &pBackBuffer ) != S_OK

g_pd3dDevice.CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView )
mov hr,eax
pBackBuffer.Release()
mov eax,hr
.break .if eax != S_OK

g_pImmediateContext.OMSetRenderTargets( 1, &g_pRenderTargetView, NULL )

;; Setup the viewport

pxor xmm0,xmm0
cvtsi2ss xmm0,_width
movss vp._Width,xmm0
pxor xmm0,xmm0
cvtsi2ss xmm0,height
movss vp.Height,xmm0
mov vp.MinDepth,0.0
mov vp.MaxDepth,1.0
mov vp.TopLeftX,0.0
mov vp.TopLeftY,0.0
g_pImmediateContext.RSSetViewports( 1, &vp )

mov eax,S_OK
    .until 1
    ret

InitDevice endp


;;--------------------------------------------------------------------------------------
;; Render the frame
;;--------------------------------------------------------------------------------------

Render proc

  local ColorRGBA[4]:FLOAT

    mov ColorRGBA[0],ARGB_MidnightBlue
    mov ColorRGBA[4],ARGB_MintCream
    mov ColorRGBA[8],ARGB_MistyRose
    mov ColorRGBA[12],ARGB_Moccasin

    ;; Just clear the backbuffer
    g_pImmediateContext.ClearRenderTargetView( g_pRenderTargetView, &ColorRGBA )
    g_pSwapChain.Present( 0, 0 )
    ret

Render endp

;;--------------------------------------------------------------------------------------
;; Clean up the objects we've created
;;--------------------------------------------------------------------------------------
CleanupDevice proc

    .if ( g_pImmediateContext )
g_pImmediateContext.ClearState()
    .endif
    .if ( g_pRenderTargetView )
g_pRenderTargetView.Release()
    .endif
    .if ( g_pSwapChain1 )
g_pSwapChain1.Release()
    .endif
    .if ( g_pSwapChain )
g_pSwapChain.Release()
    .endif
    .if ( g_pImmediateContext1 )
g_pImmediateContext1.Release()
    .endif
    .if ( g_pImmediateContext )
g_pImmediateContext.Release()
    .endif
    .if ( g_pd3dDevice1 )
g_pd3dDevice1.Release()
    .endif
    .if ( g_pd3dDevice )
g_pd3dDevice.Release()
    .endif
    ret

CleanupDevice endp

    end _tstart

The second sample (https://github.com/nidud/asmc/tree/master/source/test/wininc/D3D11/3) displays a triangle. The shape is a bit off for some reason but it works. The additional header files added was taken mingw so the parser seems to skip some of the arguments from the methods. I corrected the ones used in the samples but there may be a few more problems there. I may add a few more later to see how this plays out.
Title: Re: Asmc source and binaries
Post by: Greenhorn on April 16, 2018, 06:42:13 AM
Hi nidud,

in asmc's windows include files some macros are missing or not working at runtime.

These are:
winuser.inc
windef.inc    (min/max deactivated by condition NOMINMAX, remaining macros are missing)
stdlib.inc    (macros are not included here)


However, here is what I did to get these macros working:

winuser.inc
Code: [Select]
POINTSTOPOINT macro pt,pts
;//exitm <{ ( pt ) .x = LOWORD ( *  and  pts ) ; ( pt ) .y = HIWORD ( *  and  pts ) ; } >
movsx pt.POINT.x, LOWORD(pts)
movsx pt.POINT.y, HIWORD(pts)
endm
POINTTOPOINTS macro pt
exitm <( MAKELONG ( ( pt.POINT.x ) , ( pt.POINT.y ) ) ) >
endm
MAKEWPARAM macro l,h
ifdef _WIN64
if ((OPATTR (l)) and 00000100b) and ((OPATTR (h)) and 00000100b) ;; first and second argument are constants
mov r8, MAKELONG ( l , h )
else
movsxd r8, MAKELONG ( l , h )
endif
exitm <r8>
else
exitm <( MAKELONG ( l , h ) ) >
endif
endm
MAKELPARAM macro l,h
ifdef _WIN64
if ((OPATTR (l)) and 00000100b) and ((OPATTR (h)) and 00000100b) ;; first and second argument are constants
mov r9, MAKELONG ( l , h )
else
movsxd r9, MAKELONG ( l , h )
endif
exitm <r9>
else
exitm <( MAKELONG ( l , h ) ) >
endif
endm
MAKELRESULT macro l,h
ifdef _WIN64
if ((OPATTR (l)) and 00000100b) and ((OPATTR (h)) and 00000100b) ;; first and second argument are constants
mov rax, MAKELONG ( l , h )
else
movsxd rax, MAKELONG ( l , h )
endif
exitm <rax>
else
exitm <( MAKELONG ( l , h ) ) >
endif
endm

windef.inc
Code: [Select]
ifndef NOMINMAX
ifndef max
max macro a:REQ,b:REQ
local bSign
if ((OPATTR (a)) and 00000100b) and ((OPATTR (b)) and 00000100b) ;;// first and second argument are constants
if a gt b
exitm <a>
else
exitm <b>
endif
elseif ((OPATTR (a)) and 00010000b) ;;// argument is register
if (((INSTR ((SIZESTR <a>) - 2), <a>, <ax>) ge 0) or ((INSTR ((SIZESTR <a>) - 2), <a>, <ah>) ge 0) or ((INSTR ((SIZESTR <a>) - 2), <a>, <al>) ge 0))
cmp  a, b ;// macro max(a,b) from include WinDef.h
else
cmp     a, b ;// macro max(a,b) from include WinDef.inc
if     (SIZE (TYPE (a))) EQ 1
mov     al, a
elseif (SIZE (TYPE (a))) EQ 2
mov     ax, a
elseif (SIZE (TYPE (a))) EQ 4
mov     eax, a
elseif (SIZE (TYPE (a))) EQ 8
mov     rax, a
endif
endif
elseif ((OPATTR (a)) and 00000100b) ;;// constant
mov     eax, a
cmp     eax, b ;// macro max(a,b) from include WinDef.inc
else
if     (SIZE (TYPE (a))) EQ 1
mov  al, a
cmp  al, b ;// macro max(a,b) from include WinDef.inc
elseif (SIZE (TYPE (a))) EQ 2
mov     ax, a
cmp     ax, b ;// macro max(a,b) from include WinDef.inc
elseif (SIZE (TYPE (a))) EQ 4
mov     eax, a
cmp     eax, b ;// macro max(a,b) from include WinDef.inc
elseif (SIZE (TYPE (a))) EQ 8
mov     rax, a
cmp     rax, b ;// macro max(a,b) from include WinDef.inc
endif
endif

bSign = 0
if (@SizeStr(<a>) ge 9)
ifidni @SubStr(<a>, 1, 7),<sdword > ;;// check parameter "a"
bSign = 1
else
ifidni @SubStr(<a>, 1, 6),<sword >
bSign = 1
else
ifidni @SubStr(<a>, 1, 6),<sbyte >
bSign = 1
endif
endif
endif
endif
if (@SizeStr(<b>) ge 9)
ifidni @SubStr(<b>, 1, 7),<sdword > ;;// check parameter "b"
bSign = 1
else
ifidni @SubStr(<b>, 1, 6),<sword >
bSign = 1
else
ifidni @SubStr(<b>, 1, 6),<sbyte >
bSign = 1
endif
endif
endif
endif
if bSign
if     (SIZE (TYPE (a))) EQ 1
cmovge  al, b ;// signed comparison
exitm <al>
elseif (SIZE (TYPE (a))) EQ 2
cmovge  ax, b ;// signed comparison
exitm <ax>
elseif (SIZE (TYPE (a))) EQ 4
cmovge  eax, b ;// signed comparison
exitm <eax>
elseif (SIZE (TYPE (a))) EQ 8
cmovge  rax, b ;// signed comparison
exitm <rax>
endif
else
if     (SIZE (TYPE (a))) EQ 1
cmovae  al, b ;// unsigned comparison
exitm <al>
elseif (SIZE (TYPE (a))) EQ 2
cmovae  ax, b ;// unsigned comparison
exitm <ax>
elseif (SIZE (TYPE (a))) EQ 4
cmovae  eax, b ;// unsigned comparison
exitm <eax>
elseif (SIZE (TYPE (a))) EQ 8
cmovae  rax, b ;// unsigned comparison
exitm <rax>
endif
endif
endm
endif
ifndef min
min macro a:REQ,b:REQ
local bSign
if ((OPATTR (a)) and 00000100b) and ((OPATTR (b)) and 00000100b) ;;// first and second argument are constants
if a gt b
exitm <a>
else
exitm <b>
endif
elseif ((OPATTR (a)) and 00010000b) ;;// argument is register
if (((INSTR ((SIZESTR <a>) - 2), <a>, <ax>) ge 0) or ((INSTR ((SIZESTR <a>) - 2), <a>, <ah>) ge 0) or ((INSTR ((SIZESTR <a>) - 2), <a>, <al>) ge 0))
cmp  a, b ;// macro min(a,b) from include WinDef.h
else
cmp     a, b ;// macro min(a,b) from include WinDef.inc
if     (SIZE (TYPE (a))) EQ 1
mov     al, a
elseif (SIZE (TYPE (a))) EQ 2
mov     ax, a
elseif (SIZE (TYPE (a))) EQ 4
mov     eax, a
elseif (SIZE (TYPE (a))) EQ 8
mov     rax, a
endif
endif
elseif ((OPATTR (a)) and 00000100b) ;// constant
mov     eax, a
cmp     eax, b ;// macro max(a,b) from include WinDef.inc
else
if     (SIZE (TYPE (a))) EQ 1
mov     al, a ;//
cmp     al, b ;// macro min(a,b) from include WinDef.inc
elseif (SIZE (TYPE (a))) EQ 2
mov     ax, a ;//
cmp     ax, b ;// macro min(a,b) from include WinDef.inc
elseif (SIZE (TYPE (a))) EQ 4
mov     eax, a ;//
cmp     eax, b ;// macro min(a,b) from include WinDef.inc
elseif (SIZE (TYPE (a))) EQ 8
mov     rax, a
cmp     rax, b ;// macro min(a,b) from include WinDef.inc
endif
endif
bSign = 0
if (@SizeStr(<a>) ge 9)
ifidni @SubStr(<a>, 1, 7),<sdword > ;;// check parameter "a"
bSign = 1
else
ifidni @SubStr(<a>, 1, 6),<sword >
bSign = 1
else
ifidni @SubStr(<a>, 1, 6),<sbyte >
bSign = 1
endif
endif
endif
endif
if (@SizeStr(<b>) ge 9)
ifidni @SubStr(<b>, 1, 7),<sdword > ;;// check parameter "b"
bSign = 1
else
ifidni @SubStr(<b>, 1, 6),<sword >
bSign = 1
else
ifidni @SubStr(<b>, 1, 6),<sbyte >
bSign = 1
endif
endif
endif
endif
if bSign
if     (SIZE (TYPE (a))) EQ 1
cmovle  al, b ;// signed comparison
exitm <al>
elseif (SIZE (TYPE (a))) EQ 2
cmovle  ax, b ;// signed comparison
exitm <ax>
elseif (SIZE (TYPE (a))) EQ 4
cmovle  eax, b ;// signed comparison
exitm <eax>
elseif (SIZE (TYPE (a))) EQ 8
cmovle  rax, b ;// signed comparison
exitm <rax>
endif
else
if     (SIZE (TYPE (a))) EQ 1
cmovbe  al, b ;// unsigned comparison
exitm <al>
elseif (SIZE (TYPE (a))) EQ 2
cmovbe  ax, b ;// unsigned comparison
exitm <ax>
elseif (SIZE (TYPE (a))) EQ 4
cmovbe  eax, b ;// unsigned comparison
exitm <eax>
elseif (SIZE (TYPE (a))) EQ 8
cmovbe  rax, b ;// unsigned comparison
exitm <rax>
endif
endif
endm
endif
endif ;/* NOMINMAX */


MAKEWORD macro a:REQ,b:REQ
if ((OPATTR (a)) and 00000100b) and ((OPATTR (b)) and 00000100b) ;;// first and second argument are constants
exitm <( ( ( ( a )  and  0ffh )  or  ( ( b )  and  0ffh )  shl  8 ) ) >
elseif ((OPATTR (a)) and 00000100b) ;;// first argument is a constant
mov  eax, a ;// macro MAKEWORD(a,b)
if (SIZE (TYPE (b))) EQ 1
mov  cl, b
elseif (SIZE (TYPE (b))) EQ 2
mov  cx, b
elseif (SIZE (TYPE (b))) EQ 4
mov  ecx, b
elseif (SIZE (TYPE (b))) EQ 8
mov  rcx, b
endif
and  eax, 0FFh
and  ecx, 0FFh
shl  ecx, 8
or   eax, ecx
exitm <ax>
elseif ((OPATTR (b)) and 00000100b) ;;// second argument is a constant
mov  ecx, b ;// macro MAKEWORD(a,b)
if (SIZE (TYPE (a))) EQ 1
mov  al, a
elseif (SIZE (TYPE (a))) EQ 2
mov  ax, a
elseif (SIZE (TYPE (a))) EQ 4
mov  eax, a
elseif (SIZE (TYPE (a))) EQ 8
mov  rax, a
endif
and  eax, 0FFh
and  ecx, 0FFh
shl  ecx, 8
or   eax, ecx
exitm <ax>
else
if (SIZE (TYPE (a))) EQ 1
mov  al, a
elseif (SIZE (TYPE (a))) EQ 2
mov  ax, a
elseif (SIZE (TYPE (a))) EQ 4
mov  eax, a
elseif (SIZE (TYPE (a))) EQ 8
mov  rax, a
endif
if (SIZE (TYPE (b))) EQ 1
mov  cl, b
elseif (SIZE (TYPE (b))) EQ 2
mov  cx, b
elseif (SIZE (TYPE (b))) EQ 4
mov  ecx, b
elseif (SIZE (TYPE (b))) EQ 8
mov  rcx, b
endif
and eax, 0FFh ;// macro MAKEWORD(a,b)
and ecx, 0FFh
shl ecx, 8
or  eax, ecx
exitm <ax>
endif
endm

MAKELONG macro a:REQ,b:REQ
if ((OPATTR (a)) and 00000100b) and ((OPATTR (b)) and 00000100b) ;;// first and second argument are constants
exitm <( ( ( ( a )  and  0ffffh )  or  ( ( b )  and  0ffffh )  shl  16 ) ) >
elseif ((OPATTR (a)) and 00000100b) ;;// first argument is a constant
mov  eax, a ;// macro MAKELONG(a,b)
if (SIZE (TYPE (b))) EQ 1
mov  cl, b
elseif (SIZE (TYPE (b))) EQ 2
mov  cx, b
elseif (SIZE (TYPE (b))) EQ 4
mov  ecx, b
elseif (SIZE (TYPE (b))) EQ 8
mov  rcx, b
endif
and  eax, 0FFFFh
and  ecx, 0FFFFh
shl  ecx, 16
or   eax, ecx
exitm <eax>
elseif ((OPATTR (b)) and 00000100b) ;;// second argument is a constant
mov  ecx, b ;// macro MAKELONG(a,b)
if (SIZE (TYPE (a))) EQ 1
mov  al, a
elseif (SIZE (TYPE (a))) EQ 2
mov  ax, a
elseif (SIZE (TYPE (a))) EQ 4
mov  eax, a
elseif (SIZE (TYPE (a))) EQ 8
mov  rax, a
endif
and  eax, 0FFFFh
and  ecx, 0FFFFh
shl  ecx, 16
or   eax, ecx
exitm <eax>
else
if (SIZE (TYPE (a))) EQ 1
mov  al, a
elseif (SIZE (TYPE (a))) EQ 2
mov  ax, a
elseif (SIZE (TYPE (a))) EQ 4
mov  eax, a
elseif (SIZE (TYPE (a))) EQ 8
mov  rax, a
endif
if (SIZE (TYPE (b))) EQ 1
mov  cl, b
elseif (SIZE (TYPE (b))) EQ 2
mov  cx, b
elseif (SIZE (TYPE (b))) EQ 4
mov  ecx, b
elseif (SIZE (TYPE (b))) EQ 8
mov  rcx, b
endif
and  eax, 0FFFFh ;// macro MAKELONG(a,b)
and  ecx, 0FFFFh
shl  ecx, 16
or   eax, ecx
exitm <eax>
endif
endm

LOWORD macro l:REQ
if (OPATTR (l)) and 00000100b ;;// argument is constant
exitm <( ( ( ( l ) )  and  0ffffh ) ) >
else
if (OPATTR (l)) and 00010000b ;;// argument is register
if (SIZE (TYPE (l))) EQ 4
ifdifi <l>, <eax>
mov  eax, l ;// macro LOWORD(l)
endif
elseif (SIZE (TYPE (l))) EQ 8
ifdifi <l>, <rax>
mov  rax, l ;// macro LOWORD(l)
endif
else
.err <Wrong argument size in macro LOWORD.>
endif
else
if (SIZE (TYPE (l))) EQ 4
mov  eax, l ;// macro LOWORD(l)
elseif (SIZE (TYPE (l))) EQ 8
mov  rax, l ;// macro LOWORD(l)
else
.err <Wrong argument size in macro LOWORD.>
endif
endif
and  eax, 0FFFFh ;// macro LOWORD(l)
exitm <ax>
endif
endm

HIWORD macro l:REQ
if (OPATTR (l)) and 00000100b ;;// argument is constant
exitm <( ( ( ( ( l ) )  shr  16 )  and  0ffffh ) ) >
else
if (OPATTR (l)) and 00010000b ;;// argument is register
if (SIZE (TYPE (l))) EQ 4
ifdifi <l>, <eax>
mov  eax, l ;// macro HIWORD(l)
endif
elseif (SIZE (TYPE (l))) EQ 8
ifdifi <l>, <rax>
mov  rax, l ;// macro HIWORD(l)
endif
else
.err <Wrong argument size in macro HIWORD.>
endif
else
if (SIZE (TYPE (l))) EQ 4
mov  eax, l ;// macro HIWORD(l)
elseif (SIZE (TYPE (l))) EQ 8
mov  rax, l ;// macro HIWORD(l)
else
.err <Wrong argument size in macro HIWORD.>
endif
endif
shr  eax, 16 ;// macro HIWORD(l)
and  eax, 0FFFFh ;// macro HIWORD(l)
exitm <ax>
endif
endm

LOBYTE macro w:REQ
if (OPATTR (w)) and 00000100b ;;// argument is constant
exitm <( ( ( ( w ) )  and  0ffh ) ) >
else
if (OPATTR (w)) and 00010000b ;;// argument is register
if (SIZE (TYPE (w))) EQ 2
ifdifi <w>, <ax>
mov  ax, w ;// macro LOBYTE(w)
endif
elseif (SIZE (TYPE (w))) EQ 4
ifdifi <w>, <eax>
mov  eax, w ;// macro LOBYTE(w)
endif
elseif (SIZE (TYPE (w))) EQ 8
ifdifi <w>, <rax>
mov  rax, w ;// macro LOBYTE(w)
endif
else
.err <Wrong argument size in macro LOBYTE.>
endif
else
if (SIZE (TYPE (w))) EQ 2
mov  ax, w ;// macro LOBYTE(w)
elseif (SIZE (TYPE (w))) EQ 4
mov  eax, w ;// macro LOBYTE(w)
elseif (SIZE (TYPE (w))) EQ 8
mov  rax, w ;// macro LOBYTE(w)
else
.err <Wrong argument size in macro LOBYTE.>
endif
endif
and  ax, 0FFh ;// macro LOBYTE(w)
exitm <al>
endif
endm

HIBYTE macro w:REQ
if (OPATTR (w)) and 00000100b ;;// argument is constant
exitm <( ( ( ( ( w ) )  shr  8 )  and  0ffh ) ) >
else
if (OPATTR (w)) and 00010000b ;;// argument is register
if (SIZE (TYPE (w))) EQ 2
ifdifi <w>, <ax>
mov  ax, w ;// macro HIBYTE(w)
endif
elseif (SIZE (TYPE (w))) EQ 4
ifdifi <w>, <eax>
mov  eax, w ;// macro HIBYTE(w)
endif
elseif (SIZE (TYPE (w))) EQ 8
ifdifi <w>, <rax>
mov  rax, w ;// macro HIBYTE(w)
endif
else
.err <Wrong argument size in macro HIBYTE.>
endif
else
if (SIZE (TYPE (w))) EQ 2
mov  ax, w ;// macro HIBYTE(w)
elseif (SIZE (TYPE (w))) EQ 4
mov  eax, w ;// macro HIBYTE(w)
elseif (SIZE (TYPE (w))) EQ 8
mov  rax, w ;// macro HIBYTE(w)
else
.err <Wrong argument size in macro HIBYTE.>
endif
endif
shr  ax, 8 ;// macro HIBYTE(w)
and  ax, 0FFh ;// macro HIBYTE(w)
exitm <al>
endif
endm


stdlib.inc
Code: [Select]
Inserted min/max from above.
Regards
Greenhorn
Title: Re: Asmc source and binaries
Post by: nidud on April 16, 2018, 09:18:01 PM
The parser is simply not clever enough to handle all these macros so this needs some manhandling. I fixed some of them used in the test directory and removed some with conflicting names. Think most of them may work with immediate values but most likely fail on hard metal so I will look into the macros addressed above.
Title: Re: Asmc source and binaries
Post by: nidud on April 26, 2018, 02:02:20 AM
The include files uses .XLIST and .LIST to handle the listing output which is rather extensive using the windows include files. This turns the listing on regardless of the previous state so LIST(push/pop) is added to the .PRAGMA directive.

    .pragma(list(push, [0|1]))
        .pragma list(push, 0)
        .pragma list push 0

    .pragma(list(pop))
        .pragma list(pop)
        .pragma list pop

This gives an error on mismatch of push-pop as in if-endif.
I also added PACK for field alignment.

    .pragma(pack(push, <alignment>))
    .pragma(pack(pop))
Title: Re: Asmc source and binaries
Post by: nidud on May 11, 2018, 01:16:11 AM
Added CREF(push/pop) to the .PRAGMA directive for .cref/.nocref.
Title: Re: Asmc source and binaries
Post by: nidud on May 12, 2018, 06:13:03 AM
Small Windows include (https://github.com/nidud/asmc/tree/master/include) update.

Added one more COM sample (https://github.com/nidud/asmc/tree/master/source/test/wininc/IShellLink) using IShellLink from Raymond Chen (https://blogs.msdn.microsoft.com/oldnewthing/20180509-00/?p=98715).

Build 32/64-bit PE:
asmc -pe -ws test.asm
asmc -pe -ws -win64 test.asm

Code: [Select]
include windows.inc
include shlobj.inc
include stdio.inc
include tchar.inc

.data

CLSID_ShellLink                 IID _CLSID_ShellLink
IID_IShellLink                  IID _IID_IShellLinkW
IID_IPersistFile                IID _IID_IPersistFile
IID_IShellFolderViewCB          IID _IID_IShellFolderViewCB

.code

wmain proc

  local link:ptr IShellLinkW
  local file:ptr IPersistFile

    CoInitialize(NULL)
    .ifd CoCreateInstance(&CLSID_ShellLink, NULL,
            CLSCTX_INPROC_SERVER, &IID_IShellLink, &link) != S_OK

        wprintf("error: %x\n", eax)
    .else
        link.QueryInterface(&IID_IPersistFile, &file)
        link.SetPath("N:\\dir\\some file that doesn't exist.txt")
        file.Save("test.lnk", TRUE)
    .endif
    xor eax,eax
    ret

wmain endp

    end _tstart

32-bit:
Code: [Select]
_wmain  PROC NEAR
        push    ebp                                     ; 0000 _ 55
        mov     ebp, esp                                ; 0001 _ 8B. EC
        sub     esp, 8                                  ; 0003 _ 83. EC, 08
        push    0                                       ; 0006 _ 6A, 00
        call    _CoInitialize@4                         ; 0008 _ E8, 00000000(rel)
        lea     eax, [ebp-4H]                           ; 000D _ 8D. 45, FC
        push    eax                                     ; 0010 _ 50
        push    offset _IID_IShellLinkA                 ; 0011 _ 68, 00000000(d)
        push    1                                       ; 0016 _ 6A, 01
        push    0                                       ; 0018 _ 6A, 00
        push    offset _CLSID_ShellLink                 ; 001A _ 68, 00000000(d)
        call    _CoCreateInstance@20                    ; 001F _ E8, 00000000(rel)
        test    eax, eax                                ; 0024 _ 85. C0
        jz      ?_001                                   ; 0026 _ 74, 10
        push    eax                                     ; 0028 _ 50
        push    offset _DS0000                          ; 0029 _ 68, 00000000(d)
        call    _wprintf                                ; 002E _ E8, 00000000(rel)
        add     esp, 8                                  ; 0033 _ 83. C4, 08
        jmp     ?_002                                   ; 0036 _ EB, 35

?_001:  lea     eax, [ebp-8H]                           ; 0038 _ 8D. 45, F8
        push    eax                                     ; 003B _ 50
        push    offset _IID_IPersistFile                ; 003C _ 68, 00000000(d)
        push    dword ptr [ebp-4H]                      ; 0041 _ FF. 75, FC
        mov     eax, dword ptr [ebp-4H]                 ; 0044 _ 8B. 45, FC
        mov     eax, dword ptr [eax]                    ; 0047 _ 8B. 00
        call    dword ptr [eax]                         ; 0049 _ FF. 10
        push    offset _DS0001                          ; 004B _ 68, 00000000(d)
        push    dword ptr [ebp-4H]                      ; 0050 _ FF. 75, FC
        mov     eax, dword ptr [ebp-4H]                 ; 0053 _ 8B. 45, FC
        mov     eax, dword ptr [eax]                    ; 0056 _ 8B. 00
        call    dword ptr [eax+50H]                     ; 0058 _ FF. 50, 50
        push    1                                       ; 005B _ 6A, 01
        push    offset _DS0002                          ; 005D _ 68, 00000000(d)
        push    dword ptr [ebp-8H]                      ; 0062 _ FF. 75, F8
        mov     eax, dword ptr [ebp-8H]                 ; 0065 _ 8B. 45, F8
        mov     eax, dword ptr [eax]                    ; 0068 _ 8B. 00
        call    dword ptr [eax+18H]                     ; 006A _ FF. 50, 18
?_002:  xor     eax, eax                                ; 006D _ 33. C0
        mov     esp, ebp                                ; 006F _ 8B. E5
        pop     ebp                                     ; 0071 _ 5D
        ret                                             ; 0072 _ C3
_wmain  ENDP

64-bit:
Code: [Select]
wmain   PROC
        push    rbp                                     ; 0000 _ 55
        mov     rbp, rsp                                ; 0001 _ 48: 8B. EC
        sub     rsp, 64                                 ; 0004 _ 48: 83. EC, 40
        xor     rcx, rcx                                ; 0008 _ 48: 33. C9
        call    CoInitialize                            ; 000B _ E8, 00000000(rel)
        lea     rcx, [CLSID_ShellLink]                  ; 0010 _ 48: 8D. 0D, 00000000(rel)
        xor     rdx, rdx                                ; 0017 _ 48: 33. D2
        mov     r8d, 1                                  ; 001A _ 41: B8, 00000001
        lea     r9, [IID_IShellLinkA]                   ; 0020 _ 4C: 8D. 0D, 00000000(rel)
        lea     rax, [rbp-8H]                           ; 0027 _ 48: 8D. 45, F8
        mov     qword ptr [rsp+20H], rax                ; 002B _ 48: 89. 44 24, 20
        call    CoCreateInstance                        ; 0030 _ E8, 00000000(rel)
        test    eax, eax                                ; 0035 _ 85. C0
        jz      ?_001                                   ; 0037 _ 74, 10
        mov     edx, eax                                ; 0039 _ 8B. D0
        lea     rcx, [DS0000]                           ; 003B _ 48: 8D. 0D, 00000000(rel)
        call    wprintf                                 ; 0042 _ E8, 00000000(rel)
        jmp     ?_002                                   ; 0047 _ EB, 3F

?_001:  mov     rcx, qword ptr [rbp-8H]                 ; 0049 _ 48: 8B. 4D, F8
        lea     rdx, [IID_IPersistFile]                 ; 004D _ 48: 8D. 15, 00000000(rel)
        lea     r8, [rbp-10H]                           ; 0054 _ 4C: 8D. 45, F0
        mov     rax, qword ptr [rcx]                    ; 0058 _ 48: 8B. 01
        call    qword ptr [rax]                         ; 005B _ FF. 10
        mov     rcx, qword ptr [rbp-8H]                 ; 005D _ 48: 8B. 4D, F8
        lea     rdx, [DS0001]                           ; 0061 _ 48: 8D. 15, 00000000(rel)
        mov     rax, qword ptr [rcx]                    ; 0068 _ 48: 8B. 01
        call    qword ptr [rax+0A0H]                    ; 006B _ FF. 90, 000000A0
        mov     rcx, qword ptr [rbp-10H]                ; 0071 _ 48: 8B. 4D, F0
        lea     rdx, [DS0002]                           ; 0075 _ 48: 8D. 15, 00000000(rel)
        mov     r8d, 1                                  ; 007C _ 41: B8, 00000001
        mov     rax, qword ptr [rcx]                    ; 0082 _ 48: 8B. 01
        call    qword ptr [rax+30H]                     ; 0085 _ FF. 50, 30
?_002:  xor     eax, eax                                ; 0088 _ 33. C0
        leave                                           ; 008A _ C9
        ret                                             ; 008B _ C3
wmain   ENDP
Title: Re: Asmc source and binaries
Post by: nidud on May 24, 2018, 02:11:07 AM
The newer version of Visual C use __ImageBase for a relative offset calculation. This symbol is provided by the linker:

    extern IMAGE_DOS_HEADER __ImageBase;

The address is then __ImageBase + imagerel(label).

        lea     rdx, [__ImageBase]
        cmove   r8d, eax
        movsxd  rax, ecx
        cmp     r8d, dword ptr [imagerel(maxid)+rdx+rax*4]
        jge     ?_016
        mov     rax, qword ptr [imagerel(table)+rdx+rax*8]


The same using LINKW:

    .code
    ;
    ;--- define __ImageBase at the DOS "MZ" header
    ;
public __ImageBase

    org -0x1000
    __ImageBase label byte

    end


The object has to be the first linked:
    linkw system con_64 file { Image\Base.obj *.obj }

Address        Symbol
=======        ======

Module: base.obj(base.asm)
00400000       __ImageBase
Module: test.obj(test.obj)
00403d60       main
00404010*      ??_C@_0L@FLNMPOK@argc?5?$DN?5?$CFd?6?$AA@
00404020*      ??_C@_0O@JENCBAMC@argv?$FL1?$FN?5?$DN?5?$CFs?6?$AA@
00404030*      ??_C@_0O@IDKJAEIB@argv?$FL0?$FN?5?$DN?5?$CFs?6?$AA@


Test case using CL version 18 (https://github.com/nidud/asmc/tree/master/source/test/libc/CL18).
Title: Re: Asmc source and binaries
Post by: nidud on May 27, 2018, 07:26:06 PM
Microsoft sample using __ImageBase.
Code: [Select]
    page    ,132
    title   memset - set sections of memory all to one byte
;***
;memset.asm - set a section of memory to all one byte
;
;   Copyright (c) Microsoft Corporation. All rights reserved.
;
;Purpose:
;   contains the memset() routine
;
;*******************************************************************************

include ksamd64.inc
        subttl  "memset"
;***
;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value"
;
;Purpose:
;   Sets the first "count" bytes of the memory starting
;   at "dst" to the character value "value".
;
;   Algorithm:
;   char *
;   memset (dst, value, count)
;       char *dst;
;       char value;
;       size_t count;
;       {
;       char *start = dst;
;
;       while (count--)
;           *dst++ = value;
;       return(start);
;       }
;
;Entry:
;   char *dst - pointer to memory to fill with value
;   char value - value to put in dst bytes
;   size_t count - number of bytes of dst to fill
;
;Exit:
;   returns dst, with filled bytes
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************
    extrn   __favor:dword
    extrn   __ImageBase:byte

__FAVOR_ENFSTRG equ 1
__FAVOR_SMSTRG  equ 2

        LEAF_ENTRY_ARG3 memset, _TEXT, buf:ptr byte, value:byte, count:dword

        OPTION PROLOGUE:NONE, EPILOGUE:NONE

        mov     r11, rcx                        ; save destination address
        movzx   edx, dl                         ; set fill pattern
        mov     r9, 0101010101010101h           ; replicate fill over 8 bytes
        imul    r9, rdx
        cmp     r8, 16
        jbe     SetBytes16                      ; if count <= 15 use GPR stores to set
        movd    xmm0, r9                        ; bytes to store in bits [0:63]
        punpcklbw xmm0, xmm0                    ; dup bytes to [127:64]

;
; Check if strings should be used
;
        cmp     r8, 128                         ; is this a small set, size <= 128?
        ja      XmmSet                          ; if large set, use XMM set
        bt      __favor, __FAVOR_SMSTRG         ; check if string set should be used
        jnc     XmmSetSmall                     ; otherwise, use a 16-byte block set

StringSet:
        mov     eax, edx                        ; set byte to move
        mov     rdx, rdi                        ; save rdi
        mov     rdi, rcx                        ; set destination
        mov     rcx, r8                         ; set count
        rep     stosb                           ; store the bytes
        mov     rdi, rdx                        ; restore rdi
        mov     rax, r11
        ret                                     ; return

;
; Fill using SSE instructions - size must be 16 or more.
;
        ; xmm0 has the byte to store replicated to all byte positions
        ; rcx has the destination, can be overwritten
        ; r11 has the destination, must be preserved for return value
        ; r8  has the count
        align   16
XmmSet:
        bt      __favor, __FAVOR_ENFSTRG        ; check if string set should be used
        jc      StringSet

        ; Aligned stores are much faster on AMD hardware. We need to do an unaligned
        ; store of (16 - (dest mod 16)) bytes, but it's faster to just store 16 bytes
        ; and then start the aligned loop as usual at ((dest + 16) - (dest mod 16)).
        ; This results in (dest mod 16) bytes being stored twice. This is a lot faster
        ; than a bunch of code to store maybe 8 then maybe 4 then maybe 2 then maybe 1
        ; byte to achieve alignement. It could cause data breakpoints to trigger twice,
        ; but they will hit here first and hopefully you will read this comment.
        ; The fastest way to subtract (16 - (dest mod 16)) from the length is to add
        ; (original dest - aligned dest). This avoids having to calculate the value.

        movups  [rcx], xmm0                     ; store 16 unaligned from start
        add     r8, rcx                         ; r8 = dest + length
        add     rcx, 16                         ; dest = (dest + 16)
        and     rcx, -16                        ; dest = (dest + 16) - (dest mod 16)
        sub     r8, rcx                         ; r8 = remaining length

; Attempt to set 128-byte blocks.
;
XmmSetLarge:
        mov     r9, r8                          ; copy count of bytes remaining
        shr     r9, 7                           ; compute number of 128-byte blocks
        jz      XmmSetSmall                     ; if z, no 128-byte blocks to fill
;
; Set 128-byte blocks
        align   16
XmmSetLargeLoop:
        movaps  0[rcx], xmm0
        movaps  16[rcx], xmm0
        add     rcx, 128                        ; advance destination address early
        movaps  (32 - 128)[rcx], xmm0
        movaps  (48 - 128)[rcx], xmm0
        dec     r9                              ; dec block counter (set cc for jnz)
        movaps  (64 - 128)[rcx], xmm0
        movaps  (80 - 128)[rcx], xmm0
        movaps  (96 - 128)[rcx], xmm0
        movapd  (112 - 128)[rcx], xmm0
        ; to avoid generating a one-byte NOP for the 'align 16' below the previous
        ; instruction is movapd instead of movaps which is one byte longer but
        ; performs exactly the same operation.
        jnz     XmmSetLargeLoop                 ; loop if more blocks

        and     r8, 127                         ; compute remaining byte count
;
; Attempt to set 16-byte blocks
        align   16
XmmSetSmall:
        mov     r9, r8                          ; copy count of bytes remaining
        shr     r9, 4                           ; compute number of 16-byte blocks
        jz      short XmmSetTrailing

        ; This generates an 8-byte nop, which we execute once. This will change only if
        ; any of the code from msetxmm30 down is modified. The following loop thus is
        ; completely contained within one instruction decode buffer on AMD hardware.
        align   16

;
; Set 16-byte blocks
;
XmmSetSmallLoop:
        movups  [rcx], xmm0
        add     rcx, 16
        dec     r9
        jnz     short XmmSetSmallLoop

XmmSetTrailing:
        and     r8, 15                          ; compute remaining length
        jz      XmmSetReturn                    ; skip over movups if done, we could just do it anyway

        ; As at the start, we are going to do an unaligned store of 16 bytes which will overwrite
        ; some bytes already stored. The math is easier, rcx+r8 is one byte past the end, just
        ; back up 16 from there and store 16.

        movups  [rcx+r8-16], xmm0               ; write remainder, overwriting 16-r8 bytes we already wrote

XmmSetReturn:
        mov     rax, r11                        ; must return original dest that we saved in r11
        ret

;
; Jump table for fills of 15 bytes or fewer
;
        align 4
MsetTab dd  IMAGEREL msetTab00
        dd  IMAGEREL msetTab01
        dd  IMAGEREL msetTab02
        dd  IMAGEREL msetTab03
        dd  IMAGEREL msetTab04
        dd  IMAGEREL msetTab05
        dd  IMAGEREL msetTab06
        dd  IMAGEREL msetTab07
        dd  IMAGEREL msetTab08
        dd  IMAGEREL msetTab09
        dd  IMAGEREL msetTab10
        dd  IMAGEREL msetTab11
        dd  IMAGEREL msetTab12
        dd  IMAGEREL msetTab13
        dd  IMAGEREL msetTab14
        dd  IMAGEREL msetTab15
        dd  IMAGEREL msetTab16

        ; Set blocks that are less than 16 bytes long.
        ; Preconditions:
        ; rdx has the byte to fill and has been zero extended (ready for imul)
        ; rcx has dest
        ; r8 has len, r8 < 16
        ; r11 has the dest
        align   16
SetBytes16:
        mov     rdx, r9
        lea     r9, OFFSET __ImageBase
        mov     eax, [(IMAGEREL  MsetTab) + r9 +r8*4]
        add     r9, rax
        add     rcx, r8                         ; rcx is now 1 past last byte to set
        mov     rax, r11                        ; set return value
        jmp     r9


        align   16

        ; Code for setting various sized blocks up to 15 bytes long.
        ; preconditions:
        ; rcx points 1 byte beyond end of bytes to set
        ; rax has the correct return value (the original dest)
        ; each byte of the rdx reg is set to the byte to store
msetTab15:
        mov     (-15)[rcx], rdx
        ; fallthrough to 7
msetTab07:
        mov     (-7)[rcx], edx
        ;; fallthrough to 3
msetTab03:
        mov     (-3)[rcx], dx
        ; fallthrough to 1
msetTab01:
        mov     (-1)[rcx], dl
msetTab00:
        ret

        align   16
msetTab12:
        mov     (-12)[rcx], rdx
        ; fallthrough to 4
msetTab04:
        mov     (-4)[rcx], edx
        ret

msetTab09:
        mov     (-9)[rcx], rdx
        mov     (-1)[rcx], dl
        ret

        align   16
msetTab13:
        mov     (-13)[rcx], rdx
        ; fallthrough to 5
msetTab05:
        mov     (-5)[rcx], edx
        mov     (-1)[rcx], dl
        ret

        align   16
msetTab14:
        mov     (-14)[rcx], rdx
        ; fallthrough to 6
msetTab06:
        mov     (-6)[rcx], edx
        ; fallthrough to 2
msetTab02:
        mov     (-2)[rcx], dx
        ret

msetTab08:
        mov     [rax], rdx
        ret

msetTab11:
        mov     [rax], rdx
        mov     (8)[rax], dx
        mov     (10)[rax], dl
        ret

        align   16
msetTab10:
        mov     [rax], rdx
        mov     (8)[rax], dx
        ret

msetTab16:
        mov     [rax], rdx
        mov     (8)[rax], rdx
        ret

        LEAF_END memset, _TEXT

    end
Title: Re: Asmc source and binaries
Post by: jj2007 on May 27, 2018, 09:18:23 PM
Let me spare some time -and embarrassment- to the newcomers of Asmc. The help file is located at:

asmc-master\source\asmc\asmc.chm

Is there another version? https://github.com/nidud/asmc/raw/master/source/asmc/asmc.chm looks a bit empty :(
Title: Re: Asmc source and binaries
Post by: nidud on May 27, 2018, 10:17:51 PM
Think the OS puts a block on the file if you download it directly. Try right-click->property->General and see if there is a "Remove Block" option there.
Title: Re: Asmc source and binaries
Post by: jj2007 on May 27, 2018, 10:32:08 PM
It's not that empty, actually. The table of contents is there, but no content. Do you have a proper installer for AsmC which puts inc and lib files into their proper folders etc?

P.S.: This is odd. I just re-opened asmc-master\source\asmc\asmc.chm, and now it shows content, too ::)
No mentioning of the includes and libraries, though - is there a separate help file? Examples?
Title: Re: Asmc source and binaries
Post by: nidud on May 27, 2018, 10:45:02 PM
No.
Title: Re: Asmc source and binaries
Post by: nidud on May 27, 2018, 11:50:54 PM
No mentioning of the includes and libraries, though - is there a separate help file? Examples?

Assuming you have downloaded and unzipped the archive you should have something like this:

.\asmc-master
  bin
  include
  lib
  source
  dz.exe


- the include files are in the include directory
- the lib files are in the lib directory
- the source files are in the source directory

The simplest way to build the import libraries is to run the shell (dz.exe). This will setup the environment for the base directory wherever that may be.

From the shell, enter into the lib directory and select the makefile(s) and hit enter. To build the static libraries browse into the source directory and repeat the above. The examples are in the ./source/test directory.
Title: Re: Asmc source and binaries
Post by: nidud on June 13, 2018, 11:16:23 PM
Added a few updates in an attempt to build a 64-bit version of Asmc using the 64-bit library. This uses CL.EXE version 18 (Visual Studio 12) by adding the __ImageBase logic as explain above.

I converted a few of the bottleneck-function from the Asmc source, mostly ASCII to binary (numbers) and HASH algos.

The benchmark for the C/ASM implementation:

19532 ClockTicks: Asmc  32-bit asmc-lib 342K
21871 ClockTicks: Asmc  64-bit asmc-lib 448K
28392 ClockTicks: JWasm 32-bit watcom   345K
30327 ClockTicks: Uasm  64-bit windows  844K
40466 ClockTicks: Uasm  32-bit windows  723K
49375 ClockTicks: Asmc  64-bit windows  531K

Uasm uses a newer version of VS so it optimizes better than the C version of Asmc. Did a fatal mistake when installing Windows on the new (lunch) box, opted for the partition of C/D with the default size and ended up with a rather small C drive. This in turn prohibit the installation of the newest version of Visual Studio.

Asmc do not use any registers in a .switch unless the option REGAX is added. Some changes is added for the 64-bit version where R11 is used instead of RAX.

EDIT: REGAX is now set as default if -win64 used and will use R10 and R11 to render the switch.

A direct jump without testing (NOTEST) is not really possible given the code is unknown at the top so the switch will always start with a jump to the test label at the end of the switch. However, it is possible to use the list file to get the name of the label for the jump-table and use this directly:

EDIT: The NOTEST option will now issue a direct jump if used.

Code: [Select]
    .code

memcpy::
memmove::

    mov rax,rcx

    .if r8 <= 32

        option switch:table, switch:notest, switch:regax

        .switch r8

          .case 0
            ret

          .case 1
            mov cl,[rdx]
            mov [rax],cl
            ret

          .case 2,3,4
            mov cx,[rdx]
            mov dx,[rdx+r8-2]
            mov [rax+r8-2],dx
            mov [rax],cx
            ret

          .case 5,6,7,8
            mov ecx,[rdx]
            mov edx,[rdx+r8-4]
            mov [rax+r8-4],edx
            mov [rax],ecx
            ret

          .case 9,10,11,12,13,14,15,16
            mov rcx,[rdx]
            mov rdx,[rdx+r8-8]
            mov [rax],rcx
            mov [rax+r8-8],rdx
            ret

          .case 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
            movdqu xmm0,[rdx]
            movdqu xmm1,[rdx+r8-16]
            movups [rax],xmm0
            movups [rax+r8-16],xmm1
            ret
        .endsw
    .endif

    movups xmm2,[rdx]
    movdqu xmm3,[rdx+16]
    movdqu xmm4,[rdx+r8-16]
    movdqu xmm5,[rdx+r8-32]
    .if r8 > 64

        mov ecx,eax
        neg ecx
        and ecx,32-1
        add rdx,rcx
        mov r9,r8
        sub r9,rcx
        add rcx,rax
        and r9b,-32

        .if rcx > rdx

            .repeat
                sub r9,32
                movups xmm0,[rdx+r9]
                movups xmm1,[rdx+r9+16]
                movaps [rcx+r9],xmm0
                movaps [rcx+r9+16],xmm1
            .untilz
            movups [rax],xmm2
            movups [rax+16],xmm3
            movups [rax+r8-16],xmm4
            movups [rax+r8-32],xmm5
            ret
            db 5 dup(0x90)
        .endif

        lea rcx,[rcx+r9]
        lea rdx,[rdx+r9]
        neg r9
        .repeat
            movups xmm0,[rdx+r9]
            movups xmm1,[rdx+r9+16]
            movaps [rcx+r9],xmm0
            movaps [rcx+r9+16],xmm1
            add r9,32
        .untilz
    .endif
    movups [rax],xmm2
    movups [rax+16],xmm3
    movups [rax+r8-16],xmm4
    movups [rax+r8-32],xmm5
    ret

    end
Title: Re: Asmc source and binaries
Post by: nidud on June 21, 2018, 09:16:32 PM
Two more switches:
- added command line option /stackalign
- added command line option /autostack

Note: Only the first 4 characters are tested for these including /homeparams.

-home -auto -stac

I also implemented defined() as a inline directive suggested by Biterider (http://masm32.com/board/index.php?topic=7212.0). This will only work if defined is not, well, defined.

Test case:
Code: [Select]
    .486
    .model flat
    .code

__SYM__ equ 3

if defined(__SYM__) and __SYM__ ge 3
    mov eax,__SYM__
else
    .err <error>
endif

undef __SYM__

if defined(__SYM__) and __SYM__ ge 3
    .err <error>
else
    nop
endif

__SYM__ equ 2
if defined(__SYM__) and __SYM__ eq 2
    mov eax,__SYM__
else
    .err <error>
endif

undef __SYM__
__SYM__ equ <>
if defined(__SYM__)
    nop
else
    .err <error>
endif

if defined(__SYM2__) or defined(__SYM__)
    nop
else
    .err <error>
endif

if not defined(__SYM2__) and defined(__SYM__)
    nop
else
    .err <error>
endif

if defined(__SYM2__) and not defined(__SYM__)
    .err <error>
else
    nop
endif

    end

Source code for the implementation (https://github.com/nidud/asmc/commit/6d5d0fc96a25a7dc64f14c2d25b99dbe3fdd07ba#diff-fdf374e139f2458facf45cfa88e10855).
Title: Re: Asmc source and binaries
Post by: nidud on June 23, 2018, 08:53:15 AM
Made some changes to the .switch implementation.

The direct jump logic using NOTEST as explained above is now implemented. The actual jump table in 64-bit is reduced to 32-bit and there is no image relative addressing involved so the code produced may be relocated and still work.

The table now holds the size measured from the .CASE label to the .ENDSW label as appose to a QWORD address table resolved by the linker. Reducing it further to 16-bit would limit the total code size of the switch to 64K which may be more than enough in most cases, but as for now the DWORD size is used.

The minimum code in 32-bit is just on line:

    jmp table[reg*4-(min*4)]


The 64-bit version uses R10 and R11:

    lea r11,l_exit
    mov r10d,[reg*4+r11-(min*4)+(table-l_exit)]
    sub r11,r10
    jmp r11

Title: Re: Asmc source and binaries
Post by: nidud on June 23, 2018, 09:35:43 AM
Simple test case where the binary of the memcpy routine is loaded into the code segment and executed.

total [1 .. 64], 1++
  1690700 cycles 1.asm: switch
  3493186 cycles 0.asm: msvcrt.dll
hit any key to continue...


The benchmark result also begs the question if Microsoft actually use ml64 at all. I'v long suspected they never did.
Title: Re: Asmc source and binaries
Post by: Caché GB on June 23, 2018, 09:54:38 PM
Hello nidud.

If it helps, there is a  memcpy routine using SSE by MS.

Here - :\Program Files (x86)\Microsoft Visual Studio 14.0\VC\crt\src\amd64\memcpy.asm
Title: Re: Asmc source and binaries
Post by: nidud on June 23, 2018, 11:42:36 PM
We have been testing (http://masm32.com/board/index.php?topic=4067.msg43390#msg43390) many of these algoes for various platforms and I just posted one (http://masm32.com/board/index.php?topic=5929.msg77561#msg77561) of them in this tread, but the include files seems to be missing.

However, I don't think you will find any of these algos included in msvcrt.dll.
Title: Re: Asmc source and binaries
Post by: Vortex on June 24, 2018, 12:49:24 AM
However, I don't think you will find any of these algos included in msvcrt.dll.

Hi nidud,

Sorry if I am missing something but msvcrt.dll exports memcpy and a lot of traditional C functions :
Code: [Select]
\PellesC\bin\podump.exe /exports C:\WINDOWS\system32\msvcrt.dll
.
.
            ordinal  hint  address   name

            2E5   2E4  77BBD020  malloc
            2E6   2E5  77BAD656  mblen
            2E7   2E6  77BAD7EA  mbstowcs
            2E8   2E7  77BAD8E4  mbtowc
            2E9   2E8  77BD7C70  memchr
            2EA   2E9  77BD7D30  memcmp
            2EB   2EA  77BD7DF0  memcpy
            2EC   2EB  77BD8140  memmove
            2ED   2EC  77BD8490  memset
            2EE   2ED  77BDACF7  mktime
            2EF   2EE  77BE1AA0  modf
            2F0   2EF  77BC7E96  perror
            2F1   2F0  77BDE1C0  pow
            2F2   2F1  77BD27C2  printf
            2F3   2F2  77BD1DB4  putc
            2F4   2F3  77BCFED9  putchar
            2F5   2F4  77BD282D  puts
            2F6   2F5  77BD1FB7  putwc
            2F7   2F6  77BCFF04  putwchar
            2F8   2F7  77BC7FF0  qsort
            2F9   2F8  77BC612E  raise
            2FA   2F9  77BC8273  rand
            2FB   2FA  77BBD0C0  realloc
            2FC   2FB  77BB0A35  remove
            2FD   2FC  77BB1B2C  rename
            2FE   2FD  77BD28DB  rewind
            2FF   2FE  77BD2969  scanf
Title: Re: Asmc source and binaries
Post by: nidud on June 28, 2018, 04:02:51 AM
Fixed some bugs in name-mangling for vectorcall. The mangler used the global calling convention so mixing languages failed, vectorcall and fastcall in this case. This may still be a problem in 32-bit with regards to fastcall.

Added some test cases using vectorcall for linking with MSVC version 12. The DirectXMath library default to vectorcall so this was used for testing the mangler.

The _mm_ macros should be portable and work on most platforms (IE. 32/64-bit C/std/sys/fast/vector call) when fully implemented but for now only XMM are used in the test cases. The DirectXMath headers are now split into two files, one for function declarations and one for inline macros. The latter (DirectXMath.inl (https://github.com/nidud/asmc/blob/master/include/DirectXMath.inl)) will have inl_<name> macros corresponded to the function names in DirectXMath.inc (https://github.com/nidud/asmc/blob/master/include/DirectXMath.inc).

The mangler tests (https://github.com/nidud/asmc/tree/master/source/DirectXMath/test):

Using VC:
Code: [Select]
#include <stdio.h>

void __vectorcall XMScalarSinCos(float* pSin, float* pCos, float  Value);

int main(void)
{

  float pSin, pCos, Value;
  double Sin, Cos;

    Value = 0.5f;

    XMScalarSinCos(&pSin, &pCos, Value);

    Sin = (double)pSin;
    Cos = (double)pCos;

    printf("Sin: %f\nCos: %f\n", Sin, Cos);

    return 0;
}

Using Asmc:
Code: [Select]
include stdio.inc
include directxmath.inc

.code

main proc

  local pSin:float, pCos:float, Value:float
  local Sin:double, Cos:double

    mov Value,0.5

    XMScalarSinCos(&pSin, &pCos, Value)

    _mm_store_sd(Sin, _mm_cvtss_sd(_mm_load_ss(xmm0, pSin)))
    _mm_store_sd(Cos, _mm_cvtss_sd(_mm_load_ss(xmm1, pCos)))

    printf("Sin: %f\nCos: %f\n", Sin, Cos)

    xor eax,eax
    ret

main endp

    end

Code: [Select]
include stdio.inc
include directxmath.inc

.code

main proc

  local x:XMUINT4, Value:UINT, result:double

    mov Value,1
    mov x.x,5
    mov x.y,5
    mov x.z,5
    mov x.w,5

    XMConvertVectorIntToFloat(x, Value)

    movaps x,xmm0
    _mm_store_sd(result, _mm_cvtss_sd(_mm_load_ss(xmm0, x.x)))

    printf("result: %f\n", result)

    xor eax,eax
    ret

main endp

    end

Using inline macros for building the library:
Code: [Select]
include DirectXMath.inc

    .code

    option win64:rsp nosave noauto

XMMatrixPerspectiveFovLH proc XM_CALLCONV XMTHISPTR, FovAngleY:float, AspectRatio:float, NearZ:float, FarZ:float
if _XM_VECTORCALL_
    inl_XMMatrixPerspectiveFovLH(xmm0,xmm1,xmm2,xmm3)
else
    assume rcx:ptr XMMATRIX
    inl_XMMatrixPerspectiveFovLH(xmm1,xmm2,xmm3,xmm4,[rcx])
    mov rax,rcx
endif
    ret

XMMatrixPerspectiveFovLH endp

    end

Code: [Select]
include DirectXMath.inc

    .code

    option win64:rsp nosave noauto

XMMatrixTranspose proc XM_CALLCONV XMTHISPTR, AXMMATRIX
if _XM_VECTORCALL_
    inl_XMMatrixTranspose()
else
    assume rcx:ptr XMMATRIX
    assume rdx:ptr XMMATRIX
    inl_XMMatrixTranspose([rcx],[rdx])
    mov rax,rcx
endif
    ret

XMMatrixTranspose endp

    end
Title: Re: Asmc source and binaries
Post by: nidud on July 04, 2018, 09:18:42 PM
Added some extensions for return values from function calls.

Nested function calls adapts to argument size, now extended to XMM. Assigned values adapts to target size if possible, else default is used ([R|E]AX).

Code: [Select]
id1  label byte
id2  label word
id4  label dword
id8  label qword
id16 label oword

foo proc
    ret
foo endp

    add     al,   foo()
    add     ax,   foo()
    add     eax,  foo()
    add     rax,  foo()
    addps   xmm2, foo()

    mov     id1,  foo()
    mov     id2,  foo()
    mov     id4,  foo()
    mov     id8,  foo()
    movups  id16, foo()

bar proc x:real4, y:real16
    ret
bar endp

    bar(bar(xmm0, xmm1), xmm1)
Title: Re: Asmc source and binaries
Post by: nidud on July 06, 2018, 06:56:26 AM
Added more support for 32-bit vectorcall. This was rendered as a 32-bit fastcall without support for XMM and stack arguments.

This behaves a bit different from the 64-bit implementation where no stack is allocated for register arguments, so these refer directly to registers as oppose to a memory location. Register usage is limited to ECX and EDX but support up to six XMM registers (XMM0..5).

A bit clunky to use REAL8 values to XMM args given they will be needing a memory location in this case. This is done by pushing the number to the stack, load the XMM register and pop the stack:

    foo proto :real8, :real4
    foo(8.0, 4.0)
  * mov eax, 4.0
  * movd xmm1, eax
  * pushd high32 (8.0)
  * pushd low32 (8.0)
  * movq xmm0, [esp]
  * add esp, 8
  * call foo@@12

A test case is added to the regression folder (https://github.com/nidud/asmc/blob/master/source/asmc/regress/src/bin/vectorcall32.asm) for the stack versus reg usage.

I also added one more test using 32-bit in the D3D11 (https://github.com/nidud/asmc/tree/master/source/test/wininc/D3D11) directory. This from the Tutorial04.cpp file:

  This application displays a 3D cube using Direct3D 11

  http://msdn.microsoft.com/en-us/library/windows/apps/ff729721.aspx

The 32-bit binary is around 8K but uses only inline functions (macros) from the DirectXMath (https://github.com/nidud/asmc/tree/master/source/DirectXMath) library.
Title: Re: Asmc source and binaries
Post by: Caché GB on July 06, 2018, 05:20:20 PM
Hello nidud.

I must say you have an awesome project going here. Are you perhaps considering
creating some day an IDE may be something like Thomas Jaeger's Visual MASM?
Title: Re: Asmc source and binaries
Post by: nidud on July 06, 2018, 09:40:16 PM
Are you perhaps considering creating some day an IDE may be something like Thomas Jaeger's Visual MASM?

 :biggrin:

I'm a bit old-fashion so I mainly use make files and command-line tools.

Assuming this is a graphic editor I will consider this a waste of time. When writing code I only use text based IDE's without fiddling with a mouse and a mace of settings. I also find all of this (time-consuming) bling bling rather annoying that seems to crave more attention than it's actual purpose, so at best the editor should cover the whole screen.

(http://masm32.com/board/index.php?action=dlattach;topic=844.0;attach=685;image)

The simple IDE included in the Asmc package allows easy access to file handling, edit, transfer, search and many other things directly from the keyboard.
Title: Re: Asmc source and binaries
Post by: zedd151 on July 06, 2018, 10:34:36 PM
I'm a bit old-fashion so I manly use make files and command-line tools.

How about Edlin ?   :P
 
I could'nt get it to run in Win 7 - 64 b
 
So, all you get is a screen shot of it's properties page.  :biggrin:
Title: Re: Asmc source and binaries
Post by: nidud on July 06, 2018, 11:00:39 PM
 :biggrin:

copy con test.asm
Title: Re: Asmc source and binaries
Post by: Caché GB on July 09, 2018, 07:52:59 AM
Hello nidud.

If you are a bit old-fashioned I do respect that.
Thank you very much for the reply.

Title: Re: Asmc source and binaries
Post by: nidud on July 09, 2018, 09:05:20 AM
Could be I'm set in my old ways I guess but I did write a test pad (http://masm32.com/board/index.php?topic=5942.msg69531#msg69531) some time ago with syntax highlighting similar to the above so there is at least a resemblance of something.

I do however use a few IDE's so different tools for different things.
Title: Re: Asmc source and binaries
Post by: nidud on July 11, 2018, 08:34:57 AM
Next sample, Tutorial05.cpp:

    Tutorial 5: 3D Transformation

    https://msdn.microsoft.com/en-us/library/windows/apps/ff729722.aspx

Bit of a mystery this one. The Win32 PE binary works fine but the Win64 PE version seems to scale the objects (zoom) for some reason. Using the linker however (in 64-bit (https://github.com/nidud/asmc/tree/master/source/test/wininc/D3D11/5)) works fine. The build commands for all three:

Win32 PE:
    asmc -pe -gui -I\Asmc\include test.asm
Win64 PE:
    asmc -pe -win64 -gui -I\Asmc\include test.asm
Win64:
    asmc -gui -win64 test.asm
    linkw system gui_64 file test
Title: Re: Asmc source and binaries
Post by: nidud on July 14, 2018, 08:31:51 AM
Extensive use of the FLT4(value) (https://github.com/nidud/asmc/blob/master/include/xmmmacros.inc#L4) macro tend to create a lot of duplicate numbers (https://github.com/nidud/asmc/blob/master/include/DirectXMath.inl#L3048) so this now reuse the value if already defined.

The DirectXMath library now include most of the Matrix and Vector functions, 213 modules so far, but only a selected few of them are exclusive. This means you may use most of the functions directly without using the actual library.

The net benefit of using the library versus the C++ implementation with regards to size seems to be exactly 1:10, so the last sample built with full optimization is around 80K in C++. Using memory (no vectorcall) adds around 30K on top of that.

As for benchmark this is a bit tricky to do. You want full optimization applied to the library code but given the actual test code do not do anything useful this will be removed by the compiler. Using the pragma directive to enforce the meaningless call sequence, the ASM test using the same sequence with no in-lining, should produce the same results.

Code: [Select]
#pragma optimize( "", off )

void main()
{
    __int64 time_start = GetTickCount64();

    for ( int i=0; i < 1000000; i++ ) {

        DirectX::XMScalarSinCos(&Sin, &Cos, 20.5f);
        DirectX::XMVectorSinCosEst(&C1, &C2, V);
        DirectX::XMVectorModAngles( V );
        DirectX::XMVectorLog( V );
        DirectX::XMVectorSin( V );

The result from a selected few functions is 1:1. Without vectorcall the result is around 1:3.

As for function calls versus macros the functions preserves XMM6 and XMM7 (the library only use XMM0..7) and the macros allows immediate values so this will tilt the benchmark towards the latter.
Title: Re: Asmc source and binaries
Post by: Caché GB on July 16, 2018, 09:31:18 AM
Hello nidud.

You are making it very exciting to be programming DX11 in ASM.

I do like your floating point variable redundancy checking Macros.
I've been using the ones developed by savage here-

http://www.masmforum.com/board/index.php?topic=5453.0  (Reply #5)

I have now replaced then with yours.

Thank you.
Title: Re: Asmc source and binaries
Post by: nidud on July 21, 2018, 07:56:19 PM
However, I don't think you will find any of these algos included in msvcrt.dll.

Hi nidud,

Sorry if I am missing something but msvcrt.dll exports memcpy and a lot of traditional C functions :

What I suspect is that Microsoft never used ML64 in any 64-bit versions of Windows. The CRT assembler source supplied with VS do not correspond with any of the functions in the .dll files (msvcrt.dll in this case) as they do in 32-bit. There is also missing files there which makes it impossible to assemble any of the source supplied. The answer giving with regards to this also suggest 64-bit assembly is not a big priority for Microsoft.

This may explain the limitations of the assembler: they don't need it.
Title: Re: Asmc source and binaries
Post by: nidud on July 21, 2018, 08:53:55 PM
Some new updates:
- added fix for flags ZERO? || CARRY? in hll
- fixed bug in using 0.0 as argument -- asin(0.0)
- allowed support for movq rax,xmm0

The combined flags are now rendered as LE (or GT):

_mm_comile_sd macro a, b
   comisd a, b
   retm<ZERO? || CARRY?>
   endm
_mm_ucomigt_sd macro a, b
   ucomisd a, b
   retm<!(ZERO? || CARRY?)>
   endm

    .if _mm_comile_sd(xmm0, xmm1)
    .if _mm_ucomigt_sd(xmm0, xmm1)

Code: [Select]
jz ?_001  ; -- old
jnc ?_002
?_001: nop
?_002: jz ?_003
jc ?_003
nop
        ...
ja ?_001  ; -- new
nop
?_001: jbe ?_002
nop

A float value of zero was rejected as argument so this is now fixed. REAL16 const values in vectorcall are now allowed. They will be moved directly to [rsp] and loaded to a corresponded vector:

foo proto vectorcall a1:real16

    foo(-3.0)

Code: [Select]
        mov     qword ptr [rsp], 0
        mov     rax, 0C000800000000000H
        mov     qword ptr [rsp+8H], rax
        movaps  xmm0, xmmword ptr [rsp]
        call    foo@@16

Some math functions are added:
- REAL4 (https://github.com/nidud/asmc/tree/master/source/lib64/math/float) (float) - fastcall
- REAL8 (https://github.com/nidud/asmc/tree/master/source/lib64/math) (double) - fastcall
- REAL10 (https://github.com/nidud/asmc/tree/master/source/lib64/math/quad/fpu) (long double) - vectorcall
- REAL16 (https://github.com/nidud/asmc/tree/master/source/lib64/math/quad) (__float128) – vectorcall

The REAL10 version is REAL16 vectors using the FPU.
Title: Re: Asmc source and binaries
Post by: hutch-- on July 25, 2018, 06:35:13 PM
 :P

> This may explain the limitations of the assembler:

What limitations ? This sounds like propaganda.  :eusa_naughty:
Title: Re: Asmc source and binaries
Post by: nidud on July 25, 2018, 10:59:31 PM
The limitations of ML64 versus ML should be pretty obvious where the latter was made for building applications and the former is not.

One of the reasons for this is the calling convention used which, in addition to vectorcall, makes assembly more or less obsolete so that may explain the future of assembler from Microsoft's point of view.

To compete with this is difficult given you have to produce something less bloated and faster than an optimized compiler is capable of producing with at least the same readability as ML.
Title: Re: Asmc source and binaries
Post by: hutch-- on July 25, 2018, 11:35:01 PM
I have heard claptrap like this before, back in the 90s it was the TASM brigade with much to say and little performance and ML.EXE took a lot of criticism while it was being developed but MASM (ML.EXE) outlasted and out performed them all. The only real difference was that ML was part of the last commercial MASM product where the 64 bit version was developed as part of VC\VS and it was never designed as a consumer product.

MASM is not trying to be a C compiler, it is an assembler and while it is missing a few consumer luxuries, there is very little it cannot do, works fine in AVX, SSE, MMX and integer instructions and with enough pre-processor support it is already application capable. While I have a grasp of what you are designing as an asm / C hybrid, you don't have a point of comparison here, MASM is an assembler, you use CL.EXE for C code, MASM does not need to emulate it.
Title: Re: Asmc source and binaries
Post by: nidud on July 26, 2018, 01:15:43 AM
 :biggrin:

ML includes INVOKE, USES and HLL extensions like .IF, .WHILE and .REPEAT in addition handling/name-mangling for various calling conventions used by Microsoft like C, PASCAL, STDCALL and FASTCALL. ML64 includes none of these features, hence the limitations.

As for Asmc it includes all of these features and then some so there is indeed a point of comparison here.
Title: Re: Asmc source and binaries
Post by: hutch-- on July 26, 2018, 01:43:35 AM
 :biggrin:

64 bit MASM is a MACRO assembler, thus "invoke", ".if", just finished "USING" and while I personally rarely ever used .WHILE or .REPEAT in 32 bit, I have never had a problem with coding loops in either 32 bit or 64 bit MASM. Remember that MASM in 64 bit is an assembler, its not trying to be a compiler and while the pre-processor can create all sorts of toys, an assembler in a mnemonic cruncher, not a visual garbage generator.

If by "limitation" you mean its not a C compiler, you are right but then CL.EXE does C compiler just fine where MASM is an assembler and it does assembler just fine as well.

Here are some of the simpler examples, there are a lot more.


; ---------------------------------------------

msgloop proc

    USING rsi, rdi                                  ; allocate space for register list

    SaveRegs                                        ; save the registers

    xor rdi, rdi
    mov rsi, ptr$(msg)                              ; get the msg structure address
    jmp gmsg                                        ; jump directly to GetMessage()

  mloop:
    rcall TranslateMessage,rsi
    rcall DispatchMessage,rsi
  gmsg:
    test rax, rvcall(GetMessage,rsi,rdi,rdi,rdi)    ; loop until GetMessage returns zero
    jnz mloop

    RestoreRegs                                     ; restore the registers

    ret

msgloop endp

; ---------------------------------------------


A switch block.

        .switch wParam
          .case 200
            invoke SendMessage,hWin,WM_SYSCOMMAND,SC_CLOSE,NULL
          .case 300
            invoke MsgboxI,hWin, \
                   "Generic 64 bit Template written with ML64.EXE", \
                   "About Generic Template",MB_OK,10
        .endsw
Title: Re: Asmc source and binaries
Post by: hutch-- on July 26, 2018, 12:13:16 PM
Here is a high level conditional testing macro "jump" used for clear coding in complex high level code.

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

msgloop proc

    USING rsi, rdi                                  ; allocate space for register list

    SaveRegs                                        ; save the registers

    xor rdi, rdi
    mov rsi, ptr$(msg)                              ; get the msg structure address
    jmp gmsg                                        ; jump directly to GetMessage()

  mloop:
    rcall TranslateMessage,rsi
    rcall DispatchMessage,rsi
  gmsg:
    rcall GetMessage,rsi,rdi,rdi,rdi                ; loop until GetMessage returns zero
    jump mloop WHILE rax NE 0                       ; conditional testing macro

    ; -------------------------
    ; jump mloop IF rax NE 0                        ; stylistic variants
    ; jump mloop WHILE rax GT 0
    ; -------------------------

    RestoreRegs                                     ; restore the registers

    ret

msgloop endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Title: Re: Asmc source and binaries
Post by: nidud on July 28, 2018, 10:28:02 PM
Back to some tedious work of compiling help files. The HTML compiler (hhc.exe) used for the latest help files is a newer version but I failed to get the search option working using that. Could be some new methods or settings I guess but I ended up using the old HTML Help Workshop so now it seems to work as expected.

The Asmc.chm file is now all inclusive and contain all directives, symbols and operators as oppose to only include Asmc specific information and points to Jwasm for additional information, which in turn points to Masm.
Title: Re: Asmc source and binaries
Post by: HSE on July 29, 2018, 02:08:04 AM
Almost perfect  :t

    (I prefer light colors for text and dark colors for background. But perfection is very expensive  :biggrin:)
Title: Re: Asmc source and binaries
Post by: nidud on July 29, 2018, 02:24:05 AM
Almost perfect  :t

    (I prefer light colors for text and dark colors for background. But perfection is very expensive  :biggrin:)

There is a style.css file in the build directory:
https://github.com/nidud/asmc/tree/master/source/asmc/chm

This should be able to control the font and color settings I assume.
Title: Re: Asmc source and binaries
Post by: fearless on July 29, 2018, 02:47:12 AM
The search option looks like it works, i tried with the word 'Error' and it listed lots of topics
(https://s20.postimg.cc/4kbivr2x9/asmc_search.png)
Title: Re: Asmc source and binaries
Post by: nidud on July 29, 2018, 03:20:34 AM
64 bit MASM is a MACRO assembler, thus "invoke", ".if", just finished "USING"

USING is better than USES I guess but .IF and INVOKE is a problem.

Quote
If by "limitation" you mean its not a C compiler, you are right but then CL.EXE does C compiler just fine where MASM is an assembler and it does assembler just fine as well.

The evil C stuff:
.if, .else, .elseif, .endif, .while, .endw, .repeat, .until, .untilcxz, .break, .continue, invoke, .startup, .exit, .switch, .case, .default, .endsw, .for, .endf.

All this is included in the MASM64 SDK so I guess this makes it a not a C compiler but a MACRO C compiler then.

The problem at hand is that all of this is supported by (ML,) JWASM, UASM, and ASMC. In order to be able to use any of these with the masm64 include files I will suggest the following (peace-meal) addition to masm64rt.inc:
Code: [Select]
ifdef __JWASM__
    option nokeyword:<.if>
    option nokeyword:<.else>
    option nokeyword:<.elseif>
    option nokeyword:<.endif>
    option nokeyword:<.while>
    option nokeyword:<.endw>
    option nokeyword:<.repeat>
    option nokeyword:<.until>
    option nokeyword:<.untilcxz>
    option nokeyword:<.break>
    option nokeyword:<.continue>
    option nokeyword:<invoke>
    option nokeyword:<.startup>
    option nokeyword:<.exit>
endif

ifdef __ASMC__
    option nokeyword:<rip>      ; should be fixed by renaming Rip to _Rip
    option nokeyword:<.switch>
    option nokeyword:<.case>
    option nokeyword:<.default>
    option nokeyword:<.endsw>
    option nokeyword:<.for>
    option nokeyword:<.endf>
endif

ifdef __UASM__
    option nokeyword:<rip>
    option nokeyword:<.switch>
    option nokeyword:<.case>
    option nokeyword:<.default>
    option nokeyword:<.endsw>
    option nokeyword:<.for>
    option nokeyword:<.endf>
    option nokeyword:<memalign> ; this fails..
endif

And the following changes to macros64.inc line 1218:
Code: [Select]
    getattr MACRO arg
      EXITM % (opattr(arg)) and 0FFh
    ENDM

Or a more integrated solution:
Code: [Select]
ifndef __JWASM__
.if MACRO args:VARARG
SaveOutLabel
SaveCurrentLabel
J_POLY_COND LastDefLabel,FALSE,<args>
ENDM
endif

I'm adding a 64-bit version of Asmc and a test version is added here. This will default to COFF 64BIT FASTCALL and behave (eventually) more or less like ML64.

If you add this to the bin64 folder, apply the changes above, and in addition to this rename it to ml64.exe, all the samples in the examples64 folder should hopefully build without any problems.
Title: Re: Asmc source and binaries
Post by: nidud on July 29, 2018, 03:47:23 AM
Code: [Select]
include \masm32\include64\masm64rt.inc

    .code

    mov eax,0
    ret

    end

ti ml64 -c test.asm
Microsoft (R) Macro Assembler (x64) Version 14.11.25547.0
Copyright (C) Microsoft Corporation.  All rights reserved.

 Assembling: test.asm
 1778 ClockTicks: ml64 -c test.asm

ti asmc64 -c test.asm
Asmc Macro Assembler (x64) Version 2.27.32
Copyright (c) 2011-2018 The Asmc Contributors. All Rights Reserved.

 Assembling: test.asm
   62 ClockTicks: asmc64 -c test.asm

Title: Re: Asmc source and binaries
Post by: nidud on July 29, 2018, 03:51:53 AM
This seems to work:
Code: [Select]
body
{
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 80%;
  COLOR: White;
  BACKGROUND: Black;
  PADDING: 0px 0px 0px 20px;
}
Title: Re: Asmc source and binaries
Post by: HSE on July 29, 2018, 03:52:42 AM
This should be able to control the font and color settings I assume.

Just removing fixed black color of default text you can control that color from Internet Explorer. Better now  :t

Code: [Select]
body
{
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 80%;
  PADDING: 0px 0px 0px 20px;
}
Title: Re: Asmc source and binaries
Post by: nidud on July 29, 2018, 04:14:43 AM
Code: [Select]
body
{
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 80%;
  PADDING: 0px 0px 0px 20px;
}

Yes, that make sense: the default color is black anyway.
Title: Re: Asmc source and binaries
Post by: hutch-- on July 29, 2018, 11:38:21 AM
 :biggrin:
Quote
The problem at hand is that all of this is supported by (ML,) JWASM, UASM, and ASMC. In order to be able to use any of these with the masm64 include files I will suggest the following (peace-meal) addition to masm64rt.inc:
  etc ....
I think you miss the drift of 64 bit MASM, it is the 64 bit specification of MASM compatibility where the collection of Watcom forks are trying to emulate the 1990 version of MASM 6.0. While I would wish the Watcom fork guys every success, if they choose to emulate a very old design instead of the 64 bit MASM specifications, they can hardly be called MASM compatible.

> .if, .else, .elseif, .endif, .while, .endw, .repeat, .until, .untilcxz, .break, .continue, invoke, .startup, .exit, .switch, .case, .default, .endsw, .for, .endf.

I think you are talking about historical MASM notation here and some of it emulates some of the C notation but then if you want the REAL THING[tm] you simply use Microsoft's CL.EXE and you get real M$ C every time.

As far as the range of statements, ML64 is configured by its pre-processor and I suggest you are a little off the pace here, "invoke" is just a wrapper for a lower level macro, .if block notation has been up and working since I started on ML64 as I used Vasily's version, .switch was designed by Greg Falen years ago and it works just fine in 64 bit MASM, .exit is a simple macro that is a wrapper for ExitProcess(), the rest I just don't care about.

What many miss is the elegant simplicity of a dedicated 64 bit assembler, you don't have to fish through the tangled mess of 16, 32 and 64 bit options, you can do that with the 32 bit version ML.EXE. Write the prologue and epilogue code the right way and you are free of the ugly and unreliable stack twiddling and you can routinely change the procedure alignment to use any size LOCAL variable while maintaining the correct alignment.
Title: Re: Asmc source and binaries
Post by: nidud on July 29, 2018, 08:27:19 PM
 :biggrin:

The real problem here is that you use MACRO names of MASM directives that deviate from the MASM documentation (https://github.com/MicrosoftDocs/cpp-docs/tree/master/docs/assembler/masm). This creates confusion.

While I would wish the Watcom fork guys every success, if they choose to emulate a very old design instead of the 64 bit MASM specifications, they can hardly be called MASM compatible.

MASM64 doesn't provide any useful specifications to emulate. This is dictated by the ABI and compilers at this point.

Quote
I think you are talking about historical MASM notation here and some of it emulates some of the C notation but then if you want the REAL THING[tm] you simply use Microsoft's CL.EXE and you get real M$ C every time.

Good. Remove the crap then and stick to the REAL[tm] thing  :P

Quote
As far as the range of statements, ML64 is configured by its pre-processor and I suggest you are a little off the pace here, "invoke" is just a wrapper for a lower level macro,

INVOKE (https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/assembler/masm/invoke.md) is a MASM directive. The MACRO name should be different (.INVOKE maybe) to avoid confusion.

Quote
.if block notation has been up and working since I started on ML64 as I used Vasily's version,

.IF (https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/assembler/masm/dot-if.md) is a MASM directive. The MACRO name should be different to avoid confusion.

Quote
.switch was designed by Greg Falen years ago and it works just fine in 64 bit MASM,

.SWITCH (http://masm32.com/board/index.php?topic=5929.msg63009#msg63009)  is a ASMC directive. It was designed by me years ago and so was .CASE, .DEFAULT, and .ENDSW. Greg Falen designed the Switch MACRO using nested high-level .IF directives if I'm not mistaken.

Quote
.exit is a simple macro that is a wrapper for ExitProcess(), the rest I just don't care about.

.EXIT (https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/assembler/masm/dot-exit.md) is a MASM directive that Generates termination code so this actually doesn't break with the MASM documentation.

Quote
What many miss is the elegant simplicity of a dedicated 64 bit assembler, you don't have to fish through the tangled mess of 16, 32 and 64 bit options, you can do that with the 32 bit version ML.EXE. Write the prologue and epilogue code the right way and you are free of the ugly and unreliable stack twiddling and you can routinely change the procedure alignment to use any size LOCAL variable while maintaining the correct alignment.

As for JWASM you just add the command line switch -win64, so it's not really that complicated.
Title: Re: Asmc source and binaries
Post by: hutch-- on July 29, 2018, 10:26:29 PM
 :biggrin:

You would have to explain where you get this list of "should be" from. MASM compatibility is determined by MASM, not pretenders and in 64 bit ML64, is the only version of MASM and if other 64 bit assemblers do not fully comply with ML64, they are NOT MASM compatible.

Many of the second hand C brigade forget that MASM is a MACRO assembler and while it may piss them off, it is capable of configuring the basic assembler in many different ways so I would suggest that they go and sob silently about how MASM does much more than they wish to admit.

> INVOKE is a MASM directive.

No, "invoke" WAS a MASM directive in the 1990 and later versions of ML.EXE.

> .SWITCH  is a ASMC directive.

You and the rest of the world, MASM is the origin of the dot prefix and switch has been around for eternity.(in computer terms)

> .EXIT is a MASM directive

Not in ML64, .exit is a MASM macro.

> As for JWASM you just add the command line switch -win64, so it's not really that complicated.

Have you every bothered to look at the range of unintelligible options in JWASM ?

If you want to be locked into a 1990 architecture laced with the assumption that it should be a C compiler, best of luck to you but you will never achieve the elegant simplicity of 64 bit MASM while you are crippled by such assumptions. What really pisses off the pretenders is that 64 bit MASM is a powerful and flexible tool that does what its designed to do, the rest is just noise.  :P
Title: Re: Asmc source and binaries
Post by: jj2007 on July 29, 2018, 11:57:56 PM
... you will never achieve the elegant simplicity of 64 bit MASM ...

Amen 8)

Code: [Select]
.if eax{=edx
  conout "Masm64 is the greatest tool ever"
.endif
Title: Re: Asmc source and binaries
Post by: nidud on July 30, 2018, 12:08:08 AM
 :biggrin:

If you don't want your source to be able to be used by other assemblers that's just fine by me.
Title: Re: Asmc source and binaries
Post by: nidud on July 30, 2018, 12:26:03 AM
Code: [Select]
.if eax{=edx
  conout "Masm64 is the greatest tool ever"
.endif

 :biggrin:

Naming convention using well known mnemonic with already available documentation (https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/assembler/masm/operator-less-or-equal-masm-run-time.md) creates confusion:
Quote
operator <= (MASM Run Time)

Is less than or equal to. Used only within .IF, .WHILE, or .REPEAT blocks and evaluated at run time, not at assembly time.

Syntax
 
expression1 <= expression2
Title: Re: Asmc source and binaries
Post by: jj2007 on July 30, 2018, 12:36:20 AM
operator <= (MASM Run Time)

That's old outdated syntax from 1990  8)
Title: Re: Asmc source and binaries
Post by: hutch-- on July 30, 2018, 02:46:53 AM
 :biggrin:

> If you don't want your source to be able to be used by other assemblers that's just fine by me.

If other assemblers cannot read MASM source, that's fine with me.  :P

.if eax{=edx
  conout "Masm64 is the greatest tool ever"
.endif

At least put the "lf" after it. We would not want anyone to thing it was as toothless and some of the others.  :lol:

.if eax {= edx
  conout "Masm64 is the greatest tool ever",lf
.endif

There is MASM and there are imitations. In 64 bit MASM is the definition of MASM compatibility

Just to keep you smiling.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include64\masm64rt.inc

    t$ MACRO reg, quoted_text
      sas reg,quoted_text
      EXITM <reg>
    ENDM

    .code

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

entry_point proc

    USING r15

    SaveRegs

  ; ----------------------
  ; full shadow space call
  ; ----------------------
    invoke StdOut,"    This is a simple 'invoke StdOut' module call"

  ; --------------------------
  ; low overhead register call
  ; --------------------------
    rcall StdOut,chr$(13,10)

  ; --------------------------------------------
  ; assign string to local and emulate C escapes
  ; --------------------------------------------
    sas rax, cfm$("\n\t\tEmulating\n\t\tC escapes !\n\n")
    rcall StdOut,rax

    rcall MessageBox,0,t$(r10,"Text Message"),t$(r11,"Title"),MB_OK

  ; ---------
  ; .if block
  ; ---------
    mov r15, 2

    .if r15 } 1
      conout "    yes it is",lf
    .else
      conout "    no it ain't",lf
    .endif

  ; ------------
  ; switch block
  ; ------------
    mov r15, 3

    .switch r15
      .case 1
        conout "    case 1",lf
      .case 2
        conout "    case 2",lf
      .case 3
        conout "    case 3",lf
      .case 4
        conout "    case 4",lf
      .case 5
        conout "    case 5",lf
    .endsw

    waitkey "    Press a key !"

    RestoreRegs

    .exit

entry_point endp

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

    end


Title: Re: Asmc source and binaries
Post by: nidud on July 30, 2018, 10:34:15 AM
 :biggrin:

Fixed some IO bugs in the C-source which disable wild args and added a new version of ASMC64. This excludes a lot of 16/32-bit directives not used in 64-bit.

The .AMD64 and .WIN64 directives are now removed. This was a hack to enable 64-bit if no .MODEL or CPU was defined. The .WIN64:<options> is for this reason also removed: use OPTION WIN64:<...> insted.

Test case: ASMC64 -pe test.asm
Code: [Select]
include windows.inc
include conio.inc

    .code

    option switch:pascal, win64:auto

main proc uses r15

    _cputs( "    This is a simple condole output\n" )
    _cputs( "\n\t\tReal\n\t\tC escapes !\n\n" )

    MessageBox( 0, "Text Message", "Title", MB_OK )

    .if r15 > 1
        _cputs( "    yes it is\n" )
    .else
        _cputs( "    no it ain't\n" )
    .endif

    mov r15,3
    .switch r15
      .case 1: _cputs( "    case 1\n" )
      .case 2: _cputs( "    case 2\n" )
      .case 3: _cputs( "    case 3\n" )
      .case 4: _cputs( "    case 4\n" )
      .case 5: _cputs( "    case 5\n" )
    .endsw

    _cputs( "    Press a key !\r" )
    _getch()
    ret

main endp

    end main
Title: Re: Asmc source and binaries
Post by: nidud on July 30, 2018, 11:01:40 AM
Disassembly:
Code: [Select]
public main

extern _getch: near
extern _cputs: near
extern MessageBoxA: near

main    PROC
        push    r15                                     ; 0000 _ 41: 57
        sub     rsp, 32                                 ; 0002 _ 48: 83. EC, 20
        lea     rcx, [DS0000]                           ; 0006 _ 48: 8D. 0D, 00000000(rel)
        call    _cputs                                  ; 000D _ E8, 00000000(rel)
        lea     rcx, [DS0001]                           ; 0012 _ 48: 8D. 0D, 00000000(rel)
        call    _cputs                                  ; 0019 _ E8, 00000000(rel)
        xor     rcx, rcx                                ; 001E _ 48: 33. C9
        lea     rdx, [DS0002]                           ; 0021 _ 48: 8D. 15, 00000000(rel)
        lea     r8, [DS0003]                            ; 0028 _ 4C: 8D. 05, 00000000(rel)
        xor     r9d, r9d                                ; 002F _ 45: 33. C9
        call    MessageBoxA                             ; 0032 _ E8, 00000000(rel)
        cmp     r15, 1                                  ; 0037 _ 49: 83. FF, 01
        jbe     ?_001                                   ; 003B _ 76, 0E
        lea     rcx, [DS0004]                           ; 003D _ 48: 8D. 0D, 00000000(rel)
        call    _cputs                                  ; 0044 _ E8, 00000000(rel)
        jmp     ?_002                                   ; 0049 _ EB, 0C

?_001:  lea     rcx, [DS0005]                           ; 004B _ 48: 8D. 0D, 00000000(rel)
        call    _cputs                                  ; 0052 _ E8, 00000000(rel)
?_002:  mov     r15, 3                                  ; 0057 _ 49: C7. C7, 00000003
        jmp     ?_008                                   ; 005E _ EB, 46

?_003:  lea     rcx, [DS0006]                           ; 0060 _ 48: 8D. 0D, 00000000(rel)
        call    _cputs                                  ; 0067 _ E8, 00000000(rel)
        jmp     ?_009                                   ; 006C _ EB, 56

?_004:  lea     rcx, [DS0007]                           ; 006E _ 48: 8D. 0D, 00000000(rel)
        call    _cputs                                  ; 0075 _ E8, 00000000(rel)
        jmp     ?_009                                   ; 007A _ EB, 48

?_005:  lea     rcx, [DS0008]                           ; 007C _ 48: 8D. 0D, 00000000(rel)
        call    _cputs                                  ; 0083 _ E8, 00000000(rel)
        jmp     ?_009                                   ; 0088 _ EB, 3A

?_006:  lea     rcx, [DS0009]                           ; 008A _ 48: 8D. 0D, 00000000(rel)
        call    _cputs                                  ; 0091 _ E8, 00000000(rel)
        jmp     ?_009                                   ; 0096 _ EB, 2C

?_007:  lea     rcx, [DS000A]                           ; 0098 _ 48: 8D. 0D, 00000000(rel)
        call    _cputs                                  ; 009F _ E8, 00000000(rel)
        jmp     ?_009                                   ; 00A4 _ EB, 1E

?_008:  cmp     r15, 1                                  ; 00A6 _ 49: 83. FF, 01
        jz      ?_003                                   ; 00AA _ 74, B4
        cmp     r15, 2                                  ; 00AC _ 49: 83. FF, 02
        jz      ?_004                                   ; 00B0 _ 74, BC
        cmp     r15, 3                                  ; 00B2 _ 49: 83. FF, 03
        jz      ?_005                                   ; 00B6 _ 74, C4
        cmp     r15, 4                                  ; 00B8 _ 49: 83. FF, 04
        jz      ?_006                                   ; 00BC _ 74, CC
        cmp     r15, 5                                  ; 00BE _ 49: 83. FF, 05
        jz      ?_007                                   ; 00C2 _ 74, D4
?_009:  lea     rcx, [DS000B]                           ; 00C4 _ 48: 8D. 0D, 00000000(rel)
        call    _cputs                                  ; 00CB _ E8, 00000000(rel)
        call    _getch                                  ; 00D0 _ E8, 00000000(rel)
        add     rsp, 32                                 ; 00D5 _ 48: 83. C4, 20
        pop     r15                                     ; 00D9 _ 41: 5F
        ret                                             ; 00DB _ C3
main    ENDP

_text   ENDS

Code: [Select]
; Error: symbol names contain illegal characters,
; 2 Symbol names not changed

public entry_point

extern __imp_MessageBoxA: qword
extern __imp_ExitProcess: qword
extern wait_key: near
extern StdOut: near

entry_point PROC
        enter   128, 0                                  ; 0000 _ C8, 0080, 00
        sub     rsp, 112                                ; 0004 _ 48: 83. EC, 70
        mov     qword ptr [rbp-70H], r15                ; 0008 _ 4C: 89. 7D, 90
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??001F]                 ; 000C _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 0013 _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??0022]                 ; 0018 _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 001F _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rax, qword ptr [ptmp]                   ; 0024 _ 48: 8B. 05, 00000000(rel)
; Filling space: 3H
; Filler type: mov with same source and destination
;       db 48H, 8BH, 0C0H

ALIGN   2
        mov     rcx, rax                                ; 002E _ 48: 8B. C8
        call    StdOut                                  ; 0031 _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rax, qword ptr [??0030]                 ; 0036 _ 48: 8B. 05, 00000000(rel)
        mov     r10, rax                                ; 003D _ 4C: 8B. D0
; Note: Memory operand is misaligned. Performance penalty
        mov     rax, qword ptr [??0033]                 ; 0040 _ 48: 8B. 05, 00000000(rel)
        mov     r11, rax                                ; 0047 _ 4C: 8B. D8
        mov     r9, 0                                   ; 004A _ 49: C7. C1, 00000000
        mov     r8, r11                                 ; 0051 _ 4D: 8B. C3
        mov     rdx, r10                                ; 0054 _ 49: 8B. D2
        mov     rcx, 0                                  ; 0057 _ 48: C7. C1, 00000000
        call    qword ptr [__imp_MessageBoxA]           ; 005E _ FF. 15, 00000000(rel)
        mov     r15, 2                                  ; 0064 _ 49: C7. C7, 00000002
        cmp     r15, 1                                  ; 006B _ 49: 83. FF, 01
        jbe     ?_001                                   ; 006F _ 76, 1A
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??003F]                 ; 0071 _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 0078 _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??004A]                 ; 007D _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 0084 _ E8, 00000000(rel)
        jmp     ?_002                                   ; 0089 _ EB, 18

?_001:  mov     rcx, qword ptr [??0054]                 ; 008B _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 0092 _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??005F]                 ; 0097 _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 009E _ E8, 00000000(rel)
?_002:  mov     r15, 3                                  ; 00A3 _ 49: C7. C7, 00000003
        mov     rax, r15                                ; 00AA _ 49: 8B. C7
        cmp     rax, 1                                  ; 00AD _ 48: 83. F8, 01
        jnz     ?_003                                   ; 00B1 _ 75, 1A
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??0073]                 ; 00B3 _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 00BA _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??007E]                 ; 00BF _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 00C6 _ E8, 00000000(rel)
        jmp     ?_007                                   ; 00CB _ EB, 7E

?_003:  cmp     rax, 2                                  ; 00CD _ 48: 83. F8, 02
        jnz     ?_004                                   ; 00D1 _ 75, 1A
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??0091]                 ; 00D3 _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 00DA _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??009C]                 ; 00DF _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 00E6 _ E8, 00000000(rel)
        jmp     ?_007                                   ; 00EB _ EB, 5E

?_004:  cmp     rax, 3                                  ; 00ED _ 48: 83. F8, 03
        jnz     ?_005                                   ; 00F1 _ 75, 1A
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??00AF]                 ; 00F3 _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 00FA _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??00BA]                 ; 00FF _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 0106 _ E8, 00000000(rel)
        jmp     ?_007                                   ; 010B _ EB, 3E

?_005:  cmp     rax, 4                                  ; 010D _ 48: 83. F8, 04
        jnz     ?_006                                   ; 0111 _ 75, 1A
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??00CD]                 ; 0113 _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 011A _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??00D8]                 ; 011F _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 0126 _ E8, 00000000(rel)
        jmp     ?_007                                   ; 012B _ EB, 1E

?_006:  cmp     rax, 5                                  ; 012D _ 48: 83. F8, 05
        jnz     ?_007                                   ; 0131 _ 75, 18
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??00EB]                 ; 0133 _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 013A _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??00F6]                 ; 013F _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 0146 _ E8, 00000000(rel)
?_007:
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??0109]                 ; 014B _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 0152 _ E8, 00000000(rel)
; Note: Memory operand is misaligned. Performance penalty
        mov     rcx, qword ptr [??0101]                 ; 0157 _ 48: 8B. 0D, 00000000(rel)
        call    StdOut                                  ; 015E _ E8, 00000000(rel)
        call    wait_key                                ; 0163 _ E8, 00000000(rel)
        mov     r15, qword ptr [rbp-70H]                ; 0168 _ 4C: 8B. 7D, 90
        mov     rcx, 0                                  ; 016C _ 48: C7. C1, 00000000
; Note: Function does not end with ret or jmp
        call    qword ptr [__imp_ExitProcess]           ; 0173 _ FF. 15, 00000000(rel)
entry_point ENDP

.text$mn ENDS
Title: Re: Asmc source and binaries
Post by: hutch-- on July 30, 2018, 03:43:06 PM
This looks OK actually, the notation is not my style but it seems to work OK. I would shoot that disassembler, ascii text data is only ever byte aligned so its noise for nothing.
Title: Re: Asmc source and binaries
Post by: jj2007 on July 30, 2018, 07:02:36 PM
    _cputs( "    This is a simple condole output\n" )

My condolences :icon14:
Title: Re: Asmc source and binaries
Post by: nidud on July 30, 2018, 09:08:36 PM
This looks OK actually, the notation is not my style but it seems to work OK. I would shoot that disassembler, ascii text data is only ever byte aligned so its noise for nothing.

It uses MOV here so it probably a pointer that's not aligned 8.
Title: Re: Asmc source and binaries
Post by: nidud on July 30, 2018, 09:21:03 PM
    _cputs( "    This is a simple condole output\n" )

My condolences :icon14:

_cputs (https://msdn.microsoft.com/en-us/library/3w2s47z0.aspx)() and _cputws (https://msdn.microsoft.com/en-us/library/3w2s47z0.aspx)() is the simplest way to put a string to the console. It's part of LIBC and defined in conio.inc (https://github.com/nidud/asmc/blob/master/include/conio.inc#L43).

The Microsoft exsample (https://github.com/nidud/asmc/blob/master/source/test/libc/conio/_cputs/_cputs.asm):
Code: [Select]
;; compile with: Asmc64 -pe _cputs.asm
;; This program first displays a string to the console.

include conio.inc
include errno.inc

.code

print_to_console proc buffer:LPSTR

   local retval:SINT

   mov retval,_cputs( buffer )

   .if (retval)

       .if (errno == EINVAL)

         _cputs( "Invalid buffer in print_to_console.\r\n");

       .else
         _cputs( "Unexpected error in print_to_console.\r\n");
       .endif
   .endif
   ret

print_to_console endp


wprint_to_console proc wbuffer:ptr wchar_t

   local retval:SINT

   mov retval,_cputws( wbuffer )

   .if (retval)

       .if (errno == EINVAL)

         _cputws( L"Invalid buffer in print_to_console.\r\n")

       .else
         _cputws( L"Unexpected error in print_to_console.\r\n")
       .endif
   .endif
   ret

wprint_to_console endp

main proc

    ;; String to print at console.
    ;; Notice the \r (return) character.

    print_to_console( "Hello world (courtesy of _cputs)!\r\n" )
    wprint_to_console( L"Hello world (courtesy of _cputws)!\r\n" )
    ret

main endp

    end main

I needed to update errno.inc (https://github.com/nidud/asmc/blob/master/include/errno.inc) to make this work. It must be a function (_get_errno (https://github.com/nidud/asmc/blob/master/include/errno.inc#L60)()) when msvcrt.dll (https://github.com/nidud/asmc/blob/master/include/errno.inc#L10) is used.
Title: Re: Asmc source and binaries
Post by: nidud on July 30, 2018, 09:37:54 PM
The _cprintf (https://msdn.microsoft.com/en-us/library/7ax4dbdt.aspx)() exsample:

Code: [Select]
;; compile with: Asmc[64] -pe _cprintf.asm
;; This program displays some variables to the console.

include conio.inc

    .code

main proc

    local i:SINT, h:SINT, u:UINT, a:SBYTE

    mov i,-16
    mov h,29
    mov u,62511
    mov a,'A'
    s equ <"Test">

    ;; Note that console output does not translate \n as
    ;; standard output does. Use \r\n instead.
    ;;
    _cprintf( "%d  %.4x  %u  %c %s\r\n", i, h, u, a, s )
    ret

main endp

    end main
Title: Re: Asmc source and binaries
Post by: jj2007 on July 30, 2018, 10:03:01 PM
Hey, I was just pulling your leg: condole output  ;)
Title: Re: Asmc source and binaries
Post by: nidud on July 30, 2018, 10:26:43 PM
I really miss my old eyes and keyboard (http://masm32.com/board/index.php?topic=3422.msg36146#msg36146)  :lol:
Title: Re: Asmc source and binaries
Post by: nidud on August 03, 2018, 02:09:20 PM
Added vpcmpb and vpcmpub (apparently missing).

Asmc/Asmc64 is now similar to ML/ML64 where the latter default to 64-bit and don't understand .MODEL or CPU directives.

The available calling conventions in 64-bit is SYSCALL, VECTORCALL, and FASTCALL and they may all be used in the same module. Note that SYSCALL is used as calling convention for both 32 and 64-bit (Linux) in addition to also be an instruction. The command line switch -elf[64] defines _LINUX which in turn set __cdecl (https://github.com/nidud/asmc/blob/master/include/libc.inc#L36) to SYSCALL in the LIBC include files and may thus be used in Linux.
Code: [Select]
    .code

    option win64:rsp noauto

DWORD::Add proc syscall value
    add _this,value
    ret
DWORD::Add endp

p2  proc syscall a
    mov eax,a
    syscall
    ret
p2  endp

p1  proc vectorcall a
    mov eax,a
    ret
p1  endp

p3  proc
    p1(1)
    p2(2)
    ret
p3  endp

    end

Code: [Select]
   0: 03 fe                add    edi,esi
   2: c3                    ret   
   3: 8b c7                mov    eax,edi
   5: 0f 05                syscall
   7: c3                    ret   
   8: 8b 44 24 08          mov    eax,DWORD PTR [rsp+0x8]
   c: c3                    ret   
   d: 48 83 ec 60          sub    rsp,0x60
  11: b9 01 00 00 00        mov    ecx,0x1
  16: e8 ed ff ff ff        call   0x8
  1b: 48 83 c4 60          add    rsp,0x60
  1f: bf 02 00 00 00        mov    edi,0x2
  24: e8 da ff ff ff        call   0x3
  29: c3                    ret   
Title: Re: Asmc source and binaries
Post by: LiaoMi on August 03, 2018, 10:59:02 PM
64 bit MASM is a MACRO assembler, thus "invoke", ".if", just finished "USING"

USING is better than USES I guess but .IF and INVOKE is a problem.

Quote
If by "limitation" you mean its not a C compiler, you are right but then CL.EXE does C compiler just fine where MASM is an assembler and it does assembler just fine as well.

The evil C stuff:
.if, .else, .elseif, .endif, .while, .endw, .repeat, .until, .untilcxz, .break, .continue, invoke, .startup, .exit, .switch, .case, .default, .endsw, .for, .endf.

All this is included in the MASM64 SDK so I guess this makes it a not a C compiler but a MACRO C compiler then.

The problem at hand is that all of this is supported by (ML,) JWASM, UASM, and ASMC. In order to be able to use any of these with the masm64 include files I will suggest the following (peace-meal) addition to masm64rt.inc:
Code: [Select]
ifdef __JWASM__
    option nokeyword:<.if>
    option nokeyword:<.else>
    option nokeyword:<.elseif>
    option nokeyword:<.endif>
    option nokeyword:<.while>
    option nokeyword:<.endw>
    option nokeyword:<.repeat>
    option nokeyword:<.until>
    option nokeyword:<.untilcxz>
    option nokeyword:<.break>
    option nokeyword:<.continue>
    option nokeyword:<invoke>
    option nokeyword:<.startup>
    option nokeyword:<.exit>
endif

ifdef __ASMC__
    option nokeyword:<rip>      ; should be fixed by renaming Rip to _Rip
    option nokeyword:<.switch>
    option nokeyword:<.case>
    option nokeyword:<.default>
    option nokeyword:<.endsw>
    option nokeyword:<.for>
    option nokeyword:<.endf>
endif

ifdef __UASM__
    option nokeyword:<rip>
    option nokeyword:<.switch>
    option nokeyword:<.case>
    option nokeyword:<.default>
    option nokeyword:<.endsw>
    option nokeyword:<.for>
    option nokeyword:<.endf>
    option nokeyword:<memalign> ; this fails..
endif

And the following changes to macros64.inc line 1218:
Code: [Select]
    getattr MACRO arg
      EXITM % (opattr(arg)) and 0FFh
    ENDM

Or a more integrated solution:
Code: [Select]
ifndef __JWASM__
.if MACRO args:VARARG
SaveOutLabel
SaveCurrentLabel
J_POLY_COND LastDefLabel,FALSE,<args>
ENDM
endif

I'm adding a 64-bit version of Asmc and a test version is added here. This will default to COFF 64BIT FASTCALL and behave (eventually) more or less like ML64.

If you add this to the bin64 folder, apply the changes above, and in addition to this rename it to ml64.exe, all the samples in the examples64 folder should hopefully build without any problems.

 :biggrin: everything is so complicated, empty example with macros64.inc first on ml64

Code: [Select]
Assembling: mywindow1.asm
macros64.inc(845) : error A2008:syntax error : switch
macros64.inc(849) : error A2006:undefined symbol : getattr
macros64.inc(856) : error A2006:undefined symbol : getattr
macros64.inc(858) : error A2006:undefined symbol : getattr
macros64.inc(862) : error A2008:syntax error : :
macros64.inc(863) : error A2006:undefined symbol : varsize
macros64.inc(865) : error A2006:undefined symbol : varsize
macros64.inc(867) : error A2006:undefined symbol : varsize
Unknown arg
macros64.inc(873) : error A2170:directive must appear inside a macro
macros64.inc(875) : error A2008:syntax error : :
macros64.inc(876) : error A2006:undefined symbol : regsize
macros64.inc(878) : error A2006:undefined symbol : regsize
macros64.inc(880) : error A2006:undefined symbol : regsize
Unknown arg
macros64.inc(887) : error A2008:syntax error : :
macros64.inc(888) : fatal error A1008:unmatched macro nesting
Microsoft (R) Incremental Linker Version 14.11.25548.2
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1181: cannot open input file 'mywindow1.obj'
Press any key to continue . . .

I think the original macros should not be tied to system functions or or headers  :icon_confused: Even ml64 can not be represented as an absolute solution, since it is not a standard. Bottlenecks in macros must be unified, for the benefit of all.

And now on uasm64

Code: [Select]
macros64.inc(845) : Error A2210: Syntax error: MACRO arg
 macros64.inc(845): Included by
  mywindow1.asm(3): Main line code
macros64.inc(845) : Error A2143: Symbol redefinition: memalign
 macros64.inc(845): Included by
  mywindow1.asm(3): Main line code
macros64.inc(845) : Error A2082: Must be in segment block
 macros64.inc(845): Included by
  mywindow1.asm(3): Main line code
macros64.inc(849) : Error A2102: Symbol not defined : getattr
 macros64.inc(849): Included by
  mywindow1.asm(3): Main line code
macros64.inc(856) : Error A2102: Symbol not defined : getattr
 macros64.inc(856): Included by
  mywindow1.asm(3): Main line code
macros64.inc(858) : Error A2102: Symbol not defined : getattr
 macros64.inc(858): Included by
  mywindow1.asm(3): Main line code
macros64.inc(862) : Error A2047: Syntax error: Unexpected colon
 macros64.inc(862): Included by
  mywindow1.asm(3): Main line code
macros64.inc(863) : Error A2102: Symbol not defined : varsize
 macros64.inc(863): Included by
  mywindow1.asm(3): Main line code
macros64.inc(865) : Error A2102: Symbol not defined : varsize
 macros64.inc(865): Included by
  mywindow1.asm(3): Main line code
macros64.inc(867) : Error A2102: Symbol not defined : varsize
 macros64.inc(867): Included by
  mywindow1.asm(3): Main line code
Unknown arg
macros64.inc(873) : Error A2179: Directive must appear inside a macro
 macros64.inc(873): Included by
  mywindow1.asm(3): Main line code
macros64.inc(875) : Error A2047: Syntax error: Unexpected colon
 macros64.inc(875): Included by
  mywindow1.asm(3): Main line code
macros64.inc(876) : Error A2102: Symbol not defined : regsize
 macros64.inc(876): Included by
  mywindow1.asm(3): Main line code
macros64.inc(878) : Error A2102: Symbol not defined : regsize
 macros64.inc(878): Included by
  mywindow1.asm(3): Main line code
macros64.inc(880) : Error A2102: Symbol not defined : regsize
 macros64.inc(880): Included by
  mywindow1.asm(3): Main line code
Unknown arg
macros64.inc(887) : Error A2047: Syntax error: Unexpected colon
 macros64.inc(887): Included by
  mywindow1.asm(3): Main line code
macros64.inc(888) : Error A2163: Unmatched macro nesting
 macros64.inc(888): Included by
  mywindow1.asm(3): Main line code
macros64.inc(892) : Error A2210: Syntax error: .
 macros64.inc(892): Included by
  mywindow1.asm(3): Main line code
macros64.inc(893) : Error A2082: Must be in segment block
 macros64.inc(893): Included by
  mywindow1.asm(3): Main line code
macros64.inc(897) : Error A2163: Unmatched macro nesting
 macros64.inc(897): Included by
  mywindow1.asm(3): Main line code
macros64.inc(901) : Error A2210: Syntax error: MACRO _args:vararg
 macros64.inc(901): Included by
  mywindow1.asm(3): Main line code
macros64.inc(901) : Error A2082: Must be in segment block
 macros64.inc(901): Included by
  mywindow1.asm(3): Main line code
macros64.inc(901) : Error A2082: Must be in segment block
 macros64.inc(901): Included by
  mywindow1.asm(3): Main line code
macros64.inc(919) : Error A2082: Must be in segment block
 macros64.inc(919): Included by
  mywindow1.asm(3): Main line code
macros64.inc(919) : Error A2082: Must be in segment block
 macros64.inc(919): Included by
  mywindow1.asm(3): Main line code
macros64.inc(924) : Error A2163: Unmatched macro nesting
 macros64.inc(924): Included by
  mywindow1.asm(3): Main line code
macros64.inc(928) : Error A2210: Syntax error: MACRO _default:vararg
 macros64.inc(928): Included by
  mywindow1.asm(3): Main line code
macros64.inc(928) : Error A2082: Must be in segment block
 macros64.inc(928): Included by
  mywindow1.asm(3): Main line code
macros64.inc(929) : Error A2082: Must be in segment block
 macros64.inc(929): Included by
  mywindow1.asm(3): Main line code
macros64.inc(929) : Error A2082: Must be in segment block
 macros64.inc(929): Included by
  mywindow1.asm(3): Main line code
macros64.inc(930) : Error A2210: Syntax error: _default
 macros64.inc(930): Included by
  mywindow1.asm(3): Main line code
macros64.inc(931) : Error A2163: Unmatched macro nesting
 macros64.inc(931): Included by
  mywindow1.asm(3): Main line code
macros64.inc(935) : Error A2247: Directive must be in control block
 macros64.inc(935): Included by
  mywindow1.asm(3): Main line code
macros64.inc(949) : Error A2080: Block nesting error: .endif
 macros64.inc(949): Included by
  mywindow1.asm(3): Main line code
macros64.inc(951) : Error A2163: Unmatched macro nesting
 macros64.inc(951): Included by
  mywindow1.asm(3): Main line code
macros64.inc(1758) : Error A2160: INVOKE requires prototype for procedure
 macros64.inc(1758): Included by
  mywindow1.asm(3): Main line code
аааа***************************
macros64.inc(1759) : Error A2169: General Failure
 REGISTER(109)[macros64.inc]: Macro called from
  procedure_call(19)[macros64.inc]: Macro called from
   macros64.inc(1759): Included by
    mywindow1.asm(3): Main line code
Microsoft (R) Incremental Linker Version 14.11.25548.2
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1181: cannot open input file 'mywindow1.obj'
Press any key to continue . . .

All macros will be written separately from each other, for uasm64 as well  :eusa_boohoo:


Title: Re: Asmc source and binaries
Post by: hutch-- on August 04, 2018, 12:38:57 AM
Your error lists are meaningless without context. The MASM macro file is only for MASM, if you are using one of the Watcom forks, you will need to use the include files and macros that they supply.

> Even ml64 can not be represented as an absolute solution, since it is not a standard.

For MASM compatibility, MASM in 64 bit is the standard for 64 bit Windows as Microsoft use it themselves. If you are getting that many errors, there is something basic that you are doing wrong. Show us the code you are getting the errors with and someone may be able to help.
Title: Re: Asmc source and binaries
Post by: LiaoMi on August 04, 2018, 01:17:23 AM
Your error lists are meaningless without context. The MASM macro file is only for MASM, if you are using one of the Watcom forks, you will need to use the include files and macros that they supply.

> Even ml64 can not be represented as an absolute solution, since it is not a standard.

For MASM compatibility, MASM in 64 bit is the standard for 64 bit Windows as Microsoft use it themselves. If you are getting that many errors, there is something basic that you are doing wrong. Show us the code you are getting the errors with and someone may be able to help.

Hi Hutch,

Quote
empty example with macros64.inc

Title: Re: Asmc source and binaries
Post by: jj2007 on August 04, 2018, 02:08:49 AM
In order to be able to use any of these with the masm64 include files I will suggest the following (peace-meal) addition to masm64rt.inc:
Code: [Select]
ifdef __JWASM__
    option nokeyword:<.if>
    option nokeyword:<.else>
    option nokeyword:<.elseif>
    option nokeyword:<.endif>
    option nokeyword:<.while>
    option nokeyword:<.endw>
    option nokeyword:<.repeat>
    option nokeyword:<.until>
    option nokeyword:<.untilcxz>
    option nokeyword:<.break>
    option nokeyword:<.continue>
    option nokeyword:<invoke>
    option nokeyword:<.startup>
    option nokeyword:<.exit>
endif

This post has skipped my attention, thanks for pointing to it, LiaoMi. What nidud proposes is OK, although my preference would be to do it the other way round, i.e. if an assembler with HLL is detected, skip the definition of the .if etc macros:
it would still require some of Vasily's macros

It would require disabling the .if, invoke etc macros with e.g. IFIDNI @Assembler, <ML> then .if macro ...

Perhaps like this:
Code: [Select]
IFIDNI @Assembler, <ML>
  include VasilysMacros4ML64.inc   ; invoke, if else endif, repeat ... until, while ... wend, switch .. case .. endsw
ENDIF
include Macros4allAssemblers.inc
Title: Re: Asmc source and binaries
Post by: hutch-- on August 04, 2018, 12:31:18 PM
LiaoMi,

No error in correct framework.


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

    include \masm32\include64\masm64rt.inc

    .const
      Green equ 7
      Red   equ 5

    .data
      hInstance7   qword 0
      CommandLine7 qword 0
      hInstance    qword 0
      CommandLine  qword 0
      hInstance6   qword 0
      CommandLine6 qword 0

    .code

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

entry_point proc

    mov    ecx,Green
    mov    hInstance, rax
    mov    CommandLine7, rax
    mov    hInstance7, Red
    mov    CommandLine6, rax
    mov    hInstance6, Red
    mov    CommandLine, rax
    mov    ecx, eax

    waitkey
    .exit

entry_point endp

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

    end
Title: Re: Asmc source and binaries
Post by: LiaoMi on August 04, 2018, 04:45:13 PM
LiaoMi,

No error in correct framework.


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

    include \masm32\include64\masm64rt.inc

    .const
      Green equ 7
      Red   equ 5

    .data
      hInstance7   qword 0
      CommandLine7 qword 0
      hInstance    qword 0
      CommandLine  qword 0
      hInstance6   qword 0
      CommandLine6 qword 0

    .code

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

entry_point proc

    mov    ecx,Green
    mov    hInstance, rax
    mov    CommandLine7, rax
    mov    hInstance7, Red
    mov    CommandLine6, rax
    mov    hInstance6, Red
    mov    CommandLine, rax
    mov    ecx, eax

    waitkey
    .exit

entry_point endp

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

    end


Hi Hutch,

I have the same assembly errors, I think the problem is just in the SDK, with your SDK probably all going as it should. I use sdk from ToutEnMasm, I have to study each case separately, then I can say something more precisely. Thanks!
Title: Re: Asmc source and binaries
Post by: Vortex on August 04, 2018, 07:36:13 PM
LiaoMi,

No error in correct framework.

Exactly. I can assemble and link LiaoMi's example.
Title: Re: Asmc source and binaries
Post by: nidud on August 09, 2018, 09:44:34 PM
Fixed a bug in the .pragma(init(...)) directive. This always created an exit record (https://github.com/nidud/asmc/commit/2403c40a99d60aefc0046b10838273b585bee0b3#diff-b27cce03750cf5e5d0c7bebd4723e59aL80).

Asmc64 is now build as a 32-bit binary. This shaves off around 100K and makes it a bit faster than the 64-bit version. The benchmark used is the \masm32\m64lib\*.asm directory (somewhat modified) and the math test without .cpu and .model directive using ML64 version 12.

real_math:
Code: [Select]
5804 ClockTicks: ml64 -c -nologo real_math.asm
3651 ClockTicks: asmc64 -q real_math.asm

m64lib:
Code: [Select]
7270 ClockTicks: ml64.exe -c -nologo @ml.rsp
2698 ClockTicks: asmc64.exe -q @ml.rsp
Title: Re: Asmc source and binaries
Post by: jj2007 on August 10, 2018, 12:08:24 AM
Asmc64 is now build as a 32-bit binary. This shaves off around 100K and makes it a bit faster than the 64-bit version.

I love fast software, that's why I'm here :icon_mrgreen:
Title: Re: Asmc source and binaries
Post by: nidud on August 15, 2018, 05:25:10 AM
Added a AVX implementation of the memcpy() using a switch with overlapping moves. The overhang for small counts are basically removed by using this method.

The AVX 32 byte version:
Code: [Select]
    .code

    mov rax,rcx

    .if r8 <= 32

        option switch:notest

        .switch r8

          .case 0
            ret

          .case 1
            mov cl,[rdx]
            mov [rax],cl
            ret

          .case 2,3,4
            mov cx,[rdx]
            mov dx,[rdx+r8-2]
            mov [rax+r8-2],dx
            mov [rax],cx
            ret

          .case 5,6,7,8
            mov ecx,[rdx]
            mov edx,[rdx+r8-4]
            mov [rax+r8-4],edx
            mov [rax],ecx
            ret

          .case 9,10,11,12,13,14,15,16
            mov rcx,[rdx]
            mov rdx,[rdx+r8-8]
            mov [rax],rcx
            mov [rax+r8-8],rdx
            ret

          .case 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
            movdqu xmm0,[rdx]
            movdqu xmm1,[rdx+r8-16]
            movups [rax],xmm0
            movups [rax+r8-16],xmm1
            ret
        .endsw
    .endif

    vmovdqu ymm1,[rdx]
    vmovdqu ymm2,[rdx+r8-32]
    .if r8 > 64

        mov ecx,eax
        neg ecx
        and ecx,32-1
        add rdx,rcx
        mov r9,r8
        sub r9,rcx
        add rcx,rax
        and r9b,-32

        .if rcx > rdx

            .repeat
                sub r9,32
                vmovdqu ymm0,[rdx+r9]
                vmovdqa [rcx+r9],ymm0
            .untilz
            vmovdqu [rax],ymm1
            vmovdqu [rax+r8-32],ymm2
            ret
        .endif

        lea rcx,[rcx+r9]
        lea rdx,[rdx+r9]
        neg r9
        .repeat
            vmovdqu ymm0,[rdx+r9]
            vmovdqa [rcx+r9],ymm0
            add r9,32
        .untilz
    .endif
    vmovdqu [rax],ymm1
    vmovdqu [rax+r8-32],ymm2
    ret

    end

The AVX 64 byte version:
Code: [Select]
    .code

    mov rax,rcx

    .if r8 <= 64

        option switch:notest

        .switch r8

          .case 0
            ret

          .case 1
            mov cl,[rdx]
            mov [rax],cl
            ret

          .case 2,3,4
            mov cx,[rdx]
            mov dx,[rdx+r8-2]
            mov [rax+r8-2],dx
            mov [rax],cx
            ret

          .case 5,6,7,8
            mov ecx,[rdx]
            mov edx,[rdx+r8-4]
            mov [rax+r8-4],edx
            mov [rax],ecx
            ret

          .case 9,10,11,12,13,14,15,16
            mov rcx,[rdx]
            mov rdx,[rdx+r8-8]
            mov [rax],rcx
            mov [rax+r8-8],rdx
            ret

          .case 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
            movdqu xmm0,[rdx]
            movdqu xmm1,[rdx+r8-16]
            movups [rax],xmm0
            movups [rax+r8-16],xmm1
            ret

          .case 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,\
                49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64
            vmovdqu ymm0,[rdx]
            vmovdqu ymm1,[rdx+r8-32]
            vmovups [rax],ymm0
            vmovups [rax+r8-32],ymm1
            ret
        .endsw
    .endif

    vmovdqu ymm2,[rdx]
    vmovdqu ymm3,[rdx+32]
    vmovdqu ymm4,[rdx+r8-32]
    vmovdqu ymm5,[rdx+r8-64]

    .if r8 > 128

        mov ecx,eax
        neg ecx
        and ecx,64-1
        add rdx,rcx
        mov r9,r8
        sub r9,rcx
        add rcx,rax
        and r9b,-64

        .if rcx > rdx

            .repeat
                sub r9,64
                vmovdqu ymm0,[rdx+r9]
                vmovdqu ymm1,[rdx+r9+32]
                vmovdqa [rcx+r9],ymm0
                vmovdqa [rcx+r9+32],ymm1
            .untilz
            vmovdqu [rax],ymm2
            vmovdqu [rax+32],ymm3
            vmovdqu [rax+r8-32],ymm4
            vmovdqu [rax+r8-64],ymm5
            ret
            db 13 dup(0x90)
        .endif

        lea rcx,[rcx+r9]
        lea rdx,[rdx+r9]
        neg r9
        .repeat
            vmovdqu ymm0,[rdx+r9]
            vmovdqu ymm1,[rdx+r9+32]
            vmovdqa [rcx+r9],ymm0
            vmovdqa [rcx+r9+32],ymm1
            add r9,64
        .untilz
    .endif
    vmovdqu [rax],ymm2
    vmovdqu [rax+32],ymm3
    vmovdqu [rax+r8-32],ymm4
    vmovdqu [rax+r8-64],ymm5
    ret

    end


total [1 .. 4], 1++
    25764 cycles 2.asm: switch 32 AVX
    25788 cycles 1.asm: switch 32 SSE
    27684 cycles 3.asm: switch 64 AVX
    47541 cycles 0.asm: msvcrt.memcpy()

total [15 .. 17], 1++
    30200 cycles 2.asm: switch 32 AVX
    30364 cycles 3.asm: switch 64 AVX
    33621 cycles 1.asm: switch 32 SSE
    64903 cycles 0.asm: msvcrt.memcpy()

total [63 .. 65], 1++
    32243 cycles 3.asm: switch 64 AVX
    32869 cycles 2.asm: switch 32 AVX
    49630 cycles 1.asm: switch 32 SSE
    90890 cycles 0.asm: msvcrt.memcpy()

total [127 .. 129], 1++
    38979 cycles 3.asm: switch 64 AVX
    41102 cycles 2.asm: switch 32 AVX
    71012 cycles 1.asm: switch 32 SSE
   131579 cycles 0.asm: msvcrt.memcpy()

total [511 .. 513], 1++
    84769 cycles 3.asm: switch 64 AVX
    86763 cycles 2.asm: switch 32 AVX
   126420 cycles 1.asm: switch 32 SSE
   226737 cycles 0.asm: msvcrt.memcpy()

total [1023 .. 1025], 1++
   129894 cycles 3.asm: switch 64 AVX
   156393 cycles 2.asm: switch 32 AVX
   240375 cycles 1.asm: switch 32 SSE
   420802 cycles 0.asm: msvcrt.memcpy()
Title: Re: Asmc source and binaries
Post by: nidud on August 30, 2018, 02:26:05 AM
Added some updates to the System V implementation.

The full set of 14 registers is now added. The index of each register depends on usage rather than position so the first used xmm register will always be xmm0:

p14 proto syscall :byte,
                  :real8,
                  :real8,
                  :real8,
                  :sword, ; extend 2..4
                  :dword,
                  :real4,
                  :real4,
                  :real4,
                  :qword,
                  :ptr,
                  :real8,
                  :real8,
                  :byte

    invoke p14,dil,xmm0,xmm1,xmm2,si,edx,xmm3,xmm4,xmm5,rcx,r8,xmm6,xmm7,r9b

        call    p14

    invoke p14,dil,xmm0,xmm1,xmm2,sil,edx,xmm3,xmm4,xmm5,rcx,r8,xmm6,xmm7,r9b

        movsx   esi, sil ; sign extend 1..4
        call    p14

    invoke p14,0,1.0,2.0,3.0,4,5,6.0,7.0,8.0,9,10,11.0,12.0,13

        mov     r9b, 13
        mov     rax, 4028000000000000H
        movq    xmm7, rax
        mov     rax, 4026000000000000H
        movq    xmm6, rax
        mov     r8d, 10  ; 8..4
        mov     ecx, 9   ; 8..4
        mov     eax, 1090519040
        movd    xmm5, eax
        mov     eax, 1088421888
        movd    xmm4, eax
        mov     eax, 1086324736
        movd    xmm3, eax
        mov     edx, 5
        mov     esi, 4   ; 2..4
        mov     rax, 4008000000000000H
        movq    xmm2, rax
        mov     rax, 4000000000000000H
        movq    xmm1, rax
        mov     rax, 3FF0000000000000H
        movq    xmm0, rax
        xor     dil, dil
        call    p14

Title: Re: Asmc source and binaries
Post by: jj2007 on September 06, 2018, 01:01:39 PM
If code that work with ML don't work with AsmC,
   then AsmC is not compatible with ML

That seems to be correct. New version uploaded.

I tested the latest AsmC version with my major sources, including the difficult 64-bit text macro stuff posted here (http://masm32.com/board/index.php?topic=7392.msg80794#msg80794), all OK.

Speed is also fine (Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz):

RichMasm source (20,700 lines):
Code: [Select]
1200 ms AsmC
1415 ms UAsm64
1700 ms UAsm32

MasmBasic source (35,700 lines, 33 modules):
Code: [Select]
2400 ms AsmC
3200 ms UAsm64
7800 ms MASM (6.15, 10.0)

 :t
Title: Re: Asmc source and binaries
Post by: nidud on September 07, 2018, 09:06:59 AM
Added HIGH64 and LOW64 operators.

These will only work in 64-bit with assumed input of a 128-bit const value. Const values used in invoke are stored in [RSP] (aligned shadow space) using RAX and loaded into corresponding xmm registers directly. This may now be done manually.

    mov rax,LOW64  1.23456789012345678901234567890123
    mov rdx,HIGH64 1.23456789012345678901234567890123
    mov [rsp],rax
    mov [rsp+8],rdx
    movaps xmm0,[rsp]

Or as a regular __int128 value:

    INT128_MIN  equ -170141183460469231731687303715884105728
    INT128_MAX  equ  170141183460469231731687303715884105727
    UINT128_MAX equ  340282366920938463463374607431768211455

    mov rax,LOW64  1
    mov rdx,HIGH64 1

    mov rax,LOW64  -2
    mov rdx,HIGH64 -2

    mov rax,LOW64  INT128_MIN
    mov rdx,HIGH64 INT128_MIN
    mov rax,LOW64  INT128_MAX
    mov rdx,HIGH64 INT128_MAX
    mov rax,LOW64  UINT128_MAX
    mov rdx,HIGH64 UINT128_MAX