News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

JWasm64 with RadASM

Started by fearless, April 21, 2015, 10:05:51 AM

Previous topic - Next topic

fearless

So i started playing around with JWasm64 and managed to put together a package that works, and i fudged together a working addin to RadASM to use JWasm. I decided to detail my steps as much as possible so others might be able to recreate this and hopefully make it a bit easier for others to start using 64bit assembly.

Unfortunately i cant distribute the resources (except the RadASM additon for JWasm), but ive tried to list what might be needed, where it can be found and other notes that might be of use.


Software Resources

Not all of the items on the list need to be downloaded, some you might have already installed on your pc like the .net stuff, and others might take up a lot of unwanted space, or are too bloatly or will take forever to download, there is bound to be others ways to achieve the same end result.


JWasm64 Setup

I created a folder structure similar to masm32, at the root of the same drive i have masm32 installed:
     
\JWasm\bin
\JWasm\help
\JWasm\Include
\JWasm\Lib
\JWasm\Lib\x64

     
I downloaded JWasm64.zip (get it here), extracted JWasm.exe from JWasm64.zip, renamed it to JWasm64.exe and placed it in \JWasm\bin
Then i downloaded WinInc v2.08 (get it here), extracted contents of Include folder into \JWasm\Include

The next sections deal with the resources needed to compile and link, these were obtained from various folders on my local pc after having installed the Visual Studio 2013 Community Edition (get it here) and the SDKs that come with it.


Resource Compiler

Copy the following files from \Program Files (x86)\Windows Kits\8.1\bin\x86\ to \JWasm\bin:

rc.exe
rcdll.dll


Notes: Other versions of the resource compiler files seem to work, including the Masm32 versions located in Masm32\bin.


Resource Converter

Copy the following files from \Windows\Microsoft.NET\Framework\v4.0.30319 to \JWasm\bin:

cvtres.exe
cvtres.exe.config


Notes: The same files from other .NET installations seems to work, however cvtres.exe that is included with Masm32 does not seem to work. .NET Framework 4.5.1 (offline installer) can be downloaded from here


Link & Lib

Copy the following files from \Program Files (x86)\Visual Studio Community Edition\VC\bin to \JWasm\bin:

lib.exe
link.exe
link.exe.config
msobj120.dll
mspdb120.dll
mspdbcore.dll


Notes: The same files from Visual Studio 2010 seem to work


For the resources listed above, i tried x86 and x64 versions of them and didnt come across any problems.



64bit Libraries

The following sources seem to work when compiling with JWasm64 (copying them directly into \JWasm\Lib)


       
  • WinInc v2.08 Lib64 (build libraries with POLIB, see intructions)
  • PellesC libraries from Lib\Win64
  • \Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib\x64
  • \Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib\x64
  • \Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x64
  • \Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x64
RadASM Ini File

Edit radasm.ini to add JWasm as an option, restart RadASM and it will 'see' the JWasm.ini file and the extra stuff.

[Assembler]
Assembler=masm,
JWasm,GoAsm,fasm,nasm,html


Command Line Settings

For anyone not using RadASM here are the command line settings that i am using:

\JWasm\Bin\RC.EXE /V Test64.rc
\JWasm\Bin\JWASM64.EXE /c -win64 -Zp8 /Zi /win64 /D_WIN64 /Cp /nologo /W2 /I"M:\JWasm\Include" "Test64.asm"
\JWasm\Bin\LINK.EXE /SUBSYSTEM:WINDOWS /RELEASE /VERSION:4.0 /MACHINE:X64 /LIBPATH:"M:\JWasm\Lib\x64" /OUT:"Test64.exe" "Test64.obj" "Test64.res"



Other changes and notes

Start of code i added these instructions, comments indicate any notes or reasons as to there inclusion:

.686
.MMX
.XMM
.x64 ; 'Instruction or register not accepted in current CPU mode' error so it was needed to resolve this

option casemap : none ; Next few lines as per habran's post - http://masm32.com/board/index.php?topic=3795.msg39995#msg39995
option win64 : 11
option frame : auto
option stackbase : rsp

_WIN64 EQU 1 ; Just in case? works without it tho.
WINVER equ 0501h ; added due to error about ICC_STANDARD_CLASSES in CommCtrl.inc

     
Minor change of ShellAbout definition in Shellapi.inc to resolve 'error LNK2019: unresolved external symbol _imp__ShellAboutA@16' http://masm32.com/board/index.php?topic=3115.msg44167#msg44167 Other functions may require additional and/or similar changes.


JWasm for RadASM

The package is very similar to the masm one (i used that as a template of sorts to create it), and assuming you have mostly the same resources in a similar folder structure, the templates and test64 radasm project should compile. You may need to set paths in radasm to reflect any changes from the above, and change color or other preferences to suit your style, and copy and help files from masm32\help to a JWasm\help folder to allow for searching by keyword.

Extract the package into your RadASM folder, so that it has a JWasm sub folder and make sure there is a JWasm.ini file inside the RadASM folder.

Thats pretty much it. Happy coding. If i missed something or there is any issues let me know.

Edit: Test64.zip is the JWasm64 RadASM test project

Disclaimer: I dont guarentee that any of this will work or wont make you pull your hair out in frustration when something doesnt work - but fingers crossed eh?

rrr314159

#1
Hi fearless,

I don't use RadAsm so can't comment on that aspect of your post. Concerning the rest of it here are the things I've noticed.

JWasm - I use Habran's version because he fixed vsqrtpd/s, it's broken in the old version. It has many other new features which are optional. So it's worth noting the old JWasm (which is 40% smaller) works fine, except for that square function. "Works fine": - actually there are a few little problems still with both JWasm's. One, the type of YMM registers is incorrect. More important, they require you explicitly include a pointer when accessing SIMD memory. For instance,

movups oword ptr mem_128, xmm0

whereas ML64 (and common sense) doesn't require that. ML64, BTW, is superior in a few other details, but overall JWasm64 blows it away.

At the start of code all you actually need is

option casemap:none

you don't actually need .686, .MMX, or .x64. You mention u got an error message when leaving out .x64, I don't know why. Perhaps it's because of some of your JWasm switches; there, all I typically use is -win64. You also use RadAsm, .NET and a lot of other things I don't, so perhaps those require some of these extras. But you can do all normal 64-bit programming without them.

I also don't usually use option win64, frame, or stackbase. They can be useful but make sure you know what they do or they'll bite you in the ***. If you want the standard behavior as in 32-bit, leave them out (don't tell Habran).

Now, the old linker works fine, but I did need the new cvtres and lib.

Sooner or later you'll run into a problem with 64-bit addresses, don't remember the errors one gets, but there's a simple solution (of which qWord disapproves  :biggrin:) : use LARGEADDRESSAWARE:NO linker switch. That means you can't access memory beyond 4 gig. In my case, (perhaps in yours also), I don't care. Use that switch and all your addresses can remain 32-bit (except as required when interfacing with external functions such as Windows, of course). For instance you can use esp instead of rsp as the stack pointer. Particularly when converting 32-bit progs (which I've done a lot) I think it's a good way to go.

It's been a while since I hacked through these issues, but I have pages of notes about little details that come up. Mostly my notes compare ML64 and JWasm - bottom line: avoid ML64; but you're already doing that. Also your environment is so different I don't know how relevant my experience is. For example my "nvk" macros, which make it very easy to convert 32-bit progs, can't be used with Habran's win64-11 option. Anyway, if you have issues ask, I may have run into it also.

Have fun, those extra registers are worth the trouble, IMHO!

[edit] forgot to mention, u can actually do without cvtres by using JWasm for the resource files. I don't do it myself but it's straightforward, I'm sure many people here can tell u how it works. So, ignoring lib, u can actually do 64-bit with no new tools at all: regular JWasm 2.11, and the masm32 linker. Of course u need the includes from WinInc, but if anyone wants it, I've put together in one file a lot of the standard protos and equates (13 kb) which could get u started. Not that WinInc or Pelles is much trouble; the main thing u want to avoid is having to download Visual Studio, assuming you don't have it already
I am NaN ;)

fearless

#2
Thanks for the feedback rrr314159. A lot of projects work was based on habran's Simple VC13 ASM project: http://masm32.com/board/index.php?topic=3902.0, which i ran in vsce and wanted to get the resource stuff compiled into it the final exe, instead of using .rsrc sections etc that are in that example. Mainly i wanted to get version info and manifest to start with, then resource info for dialogs, menus etc - basically as much as possible like using masm with radasm - click compile, assemble, link - done.

It took some trial and error, and playing around with switches and options etc to get it to finally compile, once i was using a newer version of rc, cvtres and link - kept getting corrupt COFF error message in the output window - i assume the linker is calling cvtres to convert the res to obj to link into the main obj file?

I mentioned the .net stuff just as a reference to where people can find the cvtres, im not using it myself for anything, its just there - for whatever .net programs need it i suppose.

My main reason for creating this was to aid in creating a 64bit dll - used for plugins in the x64dbg - so far ive been limited and restricted to just being able to create for x32dbg. So i hope to be able to figure out / convert my code to 64bit style to accomplish this.

Ive been using h2incx to convert some .h files to .inc files, but im not sure that the prototype declares shouldnt be qwords instead of dwords or how to set any switches to take that into account, perhaps it cant, and ill have to manually adjust the files after converting.

Edit: Yeh, so after some playing around it was clear that the prototypes require qwords, and i had to manually adjust some structures and a few other things after, but h2incx was still useful for a first pass to convert defines, typedefs and structures.

rrr314159

#3
hi fearless,

Wish I'd been here when u asked about declaring qwords in prototypes. As u found out, yes almost all dwords have to be changed to qwords, both pointers and handles. That was the only question I could have answered! I know next to nothing about DLL's, C++, even resource files - how to use them, that's all. I focus on just writing assembler progs, mostly math stuff.

But for simply programming in 64-bit, here are a few tips you might find helpful.

No doubt u know the new ABI for Windows (note, Linux is different). First four args in RCX, RDX, R8, R9, plus shadow space reserved on stack. After those, args put on stack. All args are 8 bytes. If smaller (eg dword) expanded to 8; if larger, like a string or SIMD register, an 8-bit address is passed.

But you may not have noticed the following wrinkles. You can read that floating points are passed in XMM0 - XMM3 regs, actually they're also put in the GP register. Another point often not mentioned, VARARG floating point are NOT passed in XMM. In particular this applies to all the printf family (sscanf, etc).

Beyond those 4 gp's and 4 xmm's, also volatile are RAX, R10, R11, XMM4 and 5. Therefore non-volatile are rbx, rsi, rdi, r12, 13, 14, 15; XMM 6..15. Again, this is only Windows rules.

One gotcha, obvious once you think about it: callback functions use the new ABI. If you're used to getting an arg off the stack, now you find it in rcx, rdx. So for instance when a thread is launched its parameter is in rcx, not on the stack.

I'm sure you know about stack alignment being an issue, see my nvk post if not. If JWasm invoke ever gives you error message for stack alignment, or register overwrite, nvk fixes all such problems.

Many macros from masm32 still work in 64-bit, but one thing to look out for is the msvcrt routines. In masm they're, e.g., crt_printf, but now they're just printf. Often that one change is enough to make an old macro useable.

Another problem you're bound to run into, for some reason Intel dropped pushad and popad. So I wrote macros to replace them; seems most useful to include only the volatile registers. Often I don't want rax included since it sends back info (like error code) so made it optional:
;;*******************************
pushad MACRO raxalso:=<>
;;*******************************
    IFNB <raxalso>
        push rax
    ENDIF
    push rcx
    push rdx
    push rsi
    push rdi
    push r8
    push r9
    push r10
    push r11
ENDM
;;*******************************
popad MACRO raxalso:=<>
;;*******************************
    pop r11
    pop r10
    pop r9
    pop r8
    pop rdi
    pop rsi
    pop rdx
    pop rcx
    IFNB <raxalso>
        pop rax
    ENDIF
ENDM

Of course you can't push 32-bit registers any more, only 16 and 64 bit. So I convert some standard macros like this:
IF @WordSize EQ 4
    rax equ eax
ENDIF
;;*******************************
;; 32 or 64 bits
;; works with 2, 4 or 8 bytes, assume dest and src match
m2m MACRO dest, src
;;*******************************
    IF (type(dest) EQ @WordSize) OR (type(dest) EQ 2)
        push src
        pop dest
    ELSEIF @WordSize EQ 8   ;; 64 bit m2m'ing 4 bytes
        push rax
        mov eax, src
        mov dest, eax
        pop rax
    ELSE                    ;; 32 bit asked to m2m 8 bytes
        push dword ptr src
        pop dword ptr dest
        push dword ptr src+4
        pop dword ptr dest+4
    ENDIF
ENDM
;;*******************************

Now m2m works with 16, 32 or 64 bit. This technique, checking for TYPE 4 vs. 8, is very often useful.

All methods for 32-bit now have 64-bit versions. For instance, absolute values in ax / eax / rax:
;***********************
absolute_ax MACRO
push rdx
cwd ; sign bit into dx
xor ax, dx ; invert if negative
sub ax, dx ; add 1 if neg, ax = abs
pop rdx
ENDM
;***********************
absolute_eax MACRO
push rdx
cdq ; sign bit into edx
xor eax, edx ; invert if negative
sub eax, edx ; add 1 if neg, eax = abs
pop rdx
ENDM
;***********************
absolute_rax MACRO
push rdx
cqo ; sign bit into rdx
xor rax, rdx ; invert if negative
sub rax, rdx ; add 1 if neg, rax = abs
pop rdx
ENDM
;***********************

Of course there are big advantages to 64-bit. One is, floating point bit manipulations. In 32-bit, there are tricks that are worthwhile only for single precision, since REAL4 fits in a register; but REAL8 is 2 registers, 2 much trouble. Now all those tricks are good with REAL8. For instance
;**************************************************************
; MACROs to manipulate float bits
;**************************************************************
signbit4 equ 80000000h
signbit8 equ 8000000000000000h
nonsign4 equ 7fffffffh
nonsign8 equ 7fffffffffffffffh
exponen4 equ 7f800000h          ; 8 bits for exponent
exponen8 equ 7ff0000000000000h  ; 11 bits
mantiss4 equ 007fffffh          ; these are "after the decimal" actual val is + 1
mantiss8 equ 000fffffffffffffh
thebias4 equ 3f800000h
thebias8 equ 3ff0000000000000h

IFNDEF asignbit4 ; often constants won't work, especially long ones, need data
    .data
        asignbit4 dword 80000000h
        asignbit8 qword 8000000000000000h
        anonsign4 dword 7fffffffh
        anonsign8 qword 7fffffffffffffffh
        aexponen4 dword 7f800000h
        aexponen8 qword 7ff0000000000000h
        amantiss4 dword 007fffffh
        amantiss8 qword 000fffffffffffffh
        athebias4 dword 3f800000h
        athebias8 qword 3ff0000000000000h
    .code
ENDIF
;***********************
Chs MACRO thereal   ;; for memory or register reals
;***********************
    IF (OPATTR thereal) EQ 30h
        IF type (thereal) EQ 4
            xor thereal, signbit4
        ELSE
            xor thereal, asignbit8
        ENDIF
    ELSE
        IF type (thereal) EQ 4
            xor thereal, signbit4
        ELSE
            push rax
            mov rax, thereal
            xor rax, asignbit8
            mov thereal, rax
            pop rax
        ENDIF
    ENDIF
ENDM
;***********************
; NOTE: this uses a "print" macro like masm32's
prntparts MACRO realval ;; show signbit, exponent and mantissa
;***********************
    if type(realval) EQ 4
        mov r10d, realval
        print "real value4 %.9g, hex %x\n", realval, r10d
        mov r11d, r10d
        mov r12d, r10d
        and r10d, asignbit4
        shr r10d, 31
        and r11d, aexponen4
        sub r11d, thebias4
        shr r11d, 23
        and r12d, amantiss4
        print "sign %x, exp %d, mant %d\n", r10d, r11d, r12d
    else
        mov r10, realval
        print "real value8 %.19g, hex %x\n", realval, r10
        mov r11, r10
        mov r12, r10
        and r10, asignbit8
        shr r10, 63
        and r11, aexponen8
        sub r11, athebias8
        shr r11, 52
        and r12, amantiss8
        print "sign %x, exp %d mant %d\n", r10, r11, r12
    endif
ENDM
;***********************

... and so on, many others. These tricks are MUCH more useful now, not being limited to REAL4. Previously u often just used the same clumsier/slower method required for REAL8 for REAL4 also, instead of having 2 different techniques.

Another good one is RDTSC, which of course sends back 64-bit answer. With 32-bit u had to deal with this in 2 registers, now it's easier:
;;*******************************
RDTSC64 MACRO                           ;; rdtsc cycles => rax
;;*******************************
    push rdx
    mfence                              ;; serialize
    rdtsc
    shl rdx, 32
    or rax, rdx                         ;; 64 bits accomodates 100 yrs of cycles
    pop rdx
ENDM
;;*******************************
;; use like, e.g., mov rcx, @RDTSC64()
@RDTSC64 MACRO                           ;; rdtsc cycles returned, rax used
;;*******************************
    push rdx
    mfence
    rdtsc
    shl rdx, 32
    or rax, rdx
    pop rdx
EXITM <rax>
ENDM
;;*******************************

I have a lot of macros and techniques like these for just basic 64-bit programming. If any of this is useful let me know, more where that came from. For instance, macros that apply the floating point tricks to SIMD registers; in fact, a lot more SIMD stuff, not included here since it's not specifically about 64-bit. Also, timing macros using 64-bit registers, much more flexible than old 32-bit. Printing macros using 64-bit msvcrt routines. Etc.
I am NaN ;)

fearless

Thanks for the macros rrr314159, im sure they will come in handy.

Do you have any macros for outputting debug information like Donkey's vKim like tools: http://www.masmforum.com/board/index.php?topic=16317.msg154775#msg154775

I had a brief look at the defined macros, but the 64bit version of them is defined for goasm. Stored in the Debug64.a file. I had trouble trying to convert them over to a masm/jwasm supported syntax. So any stuff like that would be very handy.

LiaoMi

Quote from: fearless on April 21, 2015, 10:05:51 AM

Software Resources

Not all of the items on the list need to be downloaded, some you might have already installed on your pc like the .net stuff, and others might take up a lot of unwanted space, or are too bloatly or will take forever to download, there is bound to be others ways to achieve the same end result.


Why not use the version RadASM v3.0 ?! RadASM version 2 is easier to use with JWasm than v3 ??

fearless

I have used RadASM 3, but from what i remember at the time, is that some features where not 100% working or compatible with features from v2.x. For whatever reason i decided to stay with the 2.2.2.0 version that was as feature complete as i needed. Once v3 was on par with it i would have switch over to using that, but sadly development has slowed down completely. Unless someone knows any different?

ragdog

I use Radasm3 i  can say is better than v2

Kirkland

#8
Quote from: fearless on May 03, 2015, 03:16:42 AMI have #SNIP# but from what i remember at the time, is that some features where not 100% working or compatible with features from v2.x. For whatever reason i decided to stay with the 2.2.2.0 version that was as feature complete as i needed. Once v3 was on par with it i would have switch over to using that, but sadly development has slowed down completely. Unless someone knows any different?

I just found this out too. How do I get the old 2.2.2.0 version to make this work? I can only seem to use the latest version.

#Garbage Dispatcher Edit#
#Removed SPAM link in quoted text#


Oliver Scantleberry

I don't use anything that's "fudged together" in assembly language. I don't use jwasm (or any other "fudged" assembler), and I don't know nor care what radAsm is. Thank you anyway.