Author Topic: Difference between jwasm and uasm  (Read 1602 times)

tastewar

  • Regular Member
  • *
  • Posts: 12
Re: Difference between jwasm and uasm
« Reply #15 on: August 30, 2019, 02:23:45 AM »
More background, if anyone is still interested. We have a large project we are working on. One piece is a language interpreter with a plugin architecture that in Windows uses dll's, and in Linux will hopefully use .so files. Currently, we are able to build and run the interpreter in 64 bit Linux using jwasm. It works fine. I'm not sure how any of it is "wrong" since it's a fairly complex program, and it builds and runs, and interacts with the underlying Linux OS just fine.

We have a trivial sample plugin, written in C and built as a .so that the interpreter can load and call. However, we have a large number of such plugins that are written in our proprietary language, and that language has a compiler that originally produced MASM source as its output. On Linux, we now have it producing jwasm source. Since jwasm is dead, and is incapable of producing .so files, we would definitely like to make the switch to uasm! Since it's supposed to be compatible, we just swapped in the executable, and tried calling it instead. But clearly, it's not quite compatible, because given the same source, it isn't producing the same assembly. Specifically, the "traditional" stack frame has gone missing.

I'm attaching a slightly larger example. This one has the original (proprietary) source in the Main64.txt file, the "compiled" ASM in Main64.asm, and the jwasm produced listing file in HelloWorld64CFJW.lst and the uasm produced listing in HelloWorld64CFU.lst. If you run a diff between them, you will see that the major, functional difference is the lack of the stack frame. jwasm produces a function that includes push rbp; mov rbp,rsp; sub rsp,1200 to make space for the locals. I don't see an adjustment in rsp for local variables in the uasm listing.

I apologize if I'm missing something completely obvious/elementary here, but we thought this would be a drop-in, and it's clearly not. My hope is there is some simple command line switch we can assert to have uasm produce functions with a stack frame. Or change something in the asm our compiler is emitting to get the same result.

Anyone?

jj2007

  • Member
  • *****
  • Posts: 9782
  • Assembler is fun ;-)
    • MasmBasic
Re: Difference between jwasm and uasm
« Reply #16 on: August 30, 2019, 04:41:14 AM »
tastewar,

It seems that johnsa & habran, the two UAsm developers, are currently on holiday. They certainly will help you, even if that requires an entirely new option (but I don't think so). Few people here are familiar with Linux, so be patient, it's just a matter of a few days.

tastewar

  • Regular Member
  • *
  • Posts: 12
Re: Difference between jwasm and uasm
« Reply #17 on: August 30, 2019, 06:14:54 AM »
Thanks -- I am sticking around ;-)

AW

  • Member
  • *****
  • Posts: 2431
  • Let's Make ASM Great Again!
Re: Difference between jwasm and uasm
« Reply #18 on: August 30, 2019, 01:06:36 PM »
You appear to have disregarded, but I have posted an example where an RBP stackframe is produced. UASM will not make a stackframe, unless it is necessary - that's why I included a LOCAL variable to force it.
You can keep trying to make a stackframe appear with FRAME: AUTO or FRAME:NOAUTO, but you will never see that miracle happen. I told you, FRAME is not for that.
I will not download and look at your code, it will not bring anything new in relationship with the stackframe problem and I can not spend time on lateral issues at the moment.

tastewar

  • Regular Member
  • *
  • Posts: 12
Re: Difference between jwasm and uasm
« Reply #19 on: August 30, 2019, 09:42:11 PM »
I apologize, AW, if I didn't reply directly to your post. I certainly didn't try anything with the FRAME attribute after reading it. It may be that I posted a response that spoke about trying it, but that was before I read your post, even if it might have been after you posted it. I understand you may not have time to help me, and I certainly don't expect you to expend more effort on my issue than you feel is appropriate for you.

The second example I posted, which you are certainly free to continue to ignore, included local variables, and did not use a FRAME attribute, but produced no stack frame. So there must be more to it than that. Either we are asserting something on the command line or in our code that is causing uasm to not produce the frame, or we are failing to assert something that could. It's a difference between jwasm and uasm, and I am trying to learn what (if anything) we can do to get the older behavior, which definitely works with the bulk of our code. Also, for your (and others') information, unlike the first, the second example is not intended to produce a stand-alone runnable executable.

The first example I had posted would seg fault when built with uasm and run fine built with jwasm. I have years of experience debugging in Windows, but am very new to systems level programming on Linux, which makes it just more of a mystery.

Thanks for your contribution to the discussion!

Cheers,
--Tom

AW

  • Member
  • *****
  • Posts: 2431
  • Let's Make ASM Great Again!
Re: Difference between jwasm and uasm
« Reply #20 on: August 30, 2019, 10:42:21 PM »
@tastewar  :biggrin:

I had a look at your code and could not believe that you were using stdcall in 64-bit  :skrewy:
It does not exist stdcall for 64-bit, if you see it somewhere, it is aliased for the standard which is:
System V AMD64 ABI

OK, UASM is not aliasing or producing an error - here you are right!  :eusa_clap:

Remove the stdcall and you will see the FRAME you want.

tastewar

  • Regular Member
  • *
  • Posts: 12
Re: Difference between jwasm and uasm
« Reply #21 on: August 30, 2019, 11:06:15 PM »
Thank you, AW! I had a feeling that if the right person looked at it, they'd see what was wrong!

tastewar

  • Regular Member
  • *
  • Posts: 12
Re: Difference between jwasm and uasm
« Reply #22 on: August 30, 2019, 11:24:08 PM »
Amusingly, removing STDCALL causes jwasm to yield an error (Main64.asm(79) : Error A2091: Language type must be specified) and it seems just as unhappy with SYSCALLV.

I think also that KradMoonRa was onto the problem, but I wasn't understanding.

I tried OPTION LANGUAGE:SYSTEMV which works for uasm, but jwasm doesn't like this either.

Can anyone think of a way for me to specify this that's compatible with both jwasm and uasm?

AW

  • Member
  • *****
  • Posts: 2431
  • Let's Make ASM Great Again!
Re: Difference between jwasm and uasm
« Reply #23 on: August 31, 2019, 12:07:36 AM »
That is probably a JWASM bug that happens when there are parameters in the function. Use FASTCALL for JWASM and see  if the end result is not nonsense. I have not tested.
Use UASM for 64-bit, forget JWASM

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 6749
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Difference between jwasm and uasm
« Reply #24 on: August 31, 2019, 01:22:45 AM »
> Use UASM for 64-bit, forget JWASM

This is pretty much the action, JWASM was reasonably successful in 32 bit but Win64 uses a different ABI (Application Binary Interface) than the Intel ABI that was used in Win32 and JWASM did not do this correctly. You should NOT be using STDCALL push/call notation in 64 bit as the 64 bit system does not support it correctly.

I am familiar with this stuff in Win64 as I use the 64 bit version of MASM and had to construct the macros to do all of this. There is the first 4 stack locations that are termed "shadow space" which are filled from the 4 registers, RCX RDX R8 and R9 then any following arguments are written to the stack locations after the shadow space.

I have tested UASM with near identical code to 64 bit MASM and it performs correctly so it is properly using the Win64 ABI.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

tastewar

  • Regular Member
  • *
  • Posts: 12
Re: Difference between jwasm and uasm
« Reply #25 on: August 31, 2019, 01:47:12 AM »
On Windows we still use MASM.

jj2007

  • Member
  • *****
  • Posts: 9782
  • Assembler is fun ;-)
    • MasmBasic
Re: Difference between jwasm and uasm
« Reply #26 on: August 31, 2019, 02:04:41 AM »
If you want to keep compatibility with JWasm during the transition:

      ifdef __UASM__
         echo ** the following options are for UAsm only **
      else
         echo ** the following options are for JWasm only **
      endif

KradMoonRa

  • Regular Member
  • *
  • Posts: 44
Re: Difference between jwasm and uasm
« Reply #27 on: August 31, 2019, 03:38:01 AM »
@tastewar, Yes with JWasm using other convention name like stdcall syscal fastcal, get's ignored and defaults to systemv. With UASM that don't happens, it gets an generic epilogue prologue wen other convention is written on procedure.

Has we probably gonna have another convention for 64bits the Intel regcall, the best thing to make UASM more JWasm friendly, or (better) fix the bug,  is if in 64 bit unix* {(if callconv != systemv ||  callconv != regcall) calconv = systemv;}, hallways defaults to systemv if also declaring other (syscall, fastcall, stdcall).

And get some TODO work wen working with kernel code, because.

User-level applications use as integer registers for passing the sequence
%rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface uses %rdi,
%rsi, %rdx, %r10, %r8 and %r9.

Better explained in section A.2 AMD64 Linux Kernel Conventions in https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf
« Last Edit: August 31, 2019, 09:26:29 AM by KradMoonRa »

nidud

  • Member
  • *****
  • Posts: 1795
    • https://github.com/nidud/asmc
Re: Difference between jwasm and uasm
« Reply #28 on: August 31, 2019, 06:55:40 AM »
 :biggrin:

There are no restrictions of calling conventions in assembler with regards to bitness, so all available calling conventions in 32-bit should also work in 64-bit. As for assembler, syscall will be the preferred convention in 64-bit given it allows up to 14 registers used as arguments. The two MS versions, vectorcall and fastcall, is somewhat limited (and clunky) compare to syscall but needed (at least fastcall) for interaction with the OS.

However, this should be irrelevant for the assembler so a mixed bag of calling conventions should assemble according to the definition of the procedure:
Code: [Select]
    .code

p1  proc pascal a:ptr, b:ptr
    local x,y:ptr
    mov rax,b
    mov rdx,y
    ret
p1  endp

p2  proc c a:ptr, b:ptr
    local x,y:ptr
    invoke p1,b,y
    ret
p2  endp

p3  proc stdcall a:ptr, b:ptr
    local x,y:ptr
    invoke p2,b,y
    ret
p3  endp

p4  proc fastcall a:ptr, b:ptr
    local x,y:ptr
    invoke p3,b,y
    ret
p4  endp

p5  proc vectorcall a, b:ptr
    local x,y:ptr
    invoke p4,b,y
    ret
p5  endp

p6  proc syscall a, b
    local x,y:ptr
    invoke p5,b,y
    ret
p6  endp

    end

Generated code:
Code: [Select]
public P1
public _p2
public _p3@16
public p4
public p5@@16
public p6

P1      PROC
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     rax, qword ptr [rbp+10H]
        mov     rdx, qword ptr [rbp-10H]
        leave                           
        ret     16                     
P1      ENDP

_p2     PROC
        push    rbp                     
        mov     rbp, rsp               
        sub     rsp, 16                 
        push    qword ptr [rbp+18H]     
        push    qword ptr [rbp-10H]     
        call    P1                     
        leave                           
        ret                             
_p2     ENDP

_p3@16  PROC
        push    rbp                     
        mov     rbp, rsp               
        sub     rsp, 16                 
        push    qword ptr [rbp-10H]     
        push    qword ptr [rbp+18H]     
        call    _p2                     
        add     rsp, 16                 
        leave                           
        ret     16                     
_p3@16  ENDP

p4      PROC
        push    rbp                     
        mov     rbp, rsp               
        sub     rsp, 16                 
        push    qword ptr [rbp-10H]     
        push    qword ptr [rbp+18H]     
        call    _p3@16                 
        leave                           
        ret                             
p4      ENDP

p5@@16  PROC
        push    rbp                     
        mov     rbp, rsp               
        sub     rsp, 16                 
        sub     rsp, 32                 
        mov     rdx, qword ptr [rbp-10H]
        mov     rcx, qword ptr [rbp+18H]
        call    p4                     
        add     rsp, 32                 
        leave                           
        ret                             
p5@@16  ENDP

p6      PROC
        push    rbp                     
        mov     rbp, rsp               
        sub     rsp, 16                 
        sub     rsp, 96                 
        mov     rdx, qword ptr [rbp-10H]
        mov     ecx, esi               
        call    p5@@16                 
        add     rsp, 96                 
        leave                           
        ret                             
p6      ENDP

KradMoonRa

  • Regular Member
  • *
  • Posts: 44
Re: Difference between jwasm and uasm
« Reply #29 on: August 31, 2019, 08:40:28 AM »
@nidud
True, it's by the programmer to. In some old kernel linux distributions, any code has capable of running regarding off the caller. Currently we need to be magician to get the code running on recent linux kernel.

@tastewar
Regarding wath I talk earlier. Applied changes in uasm to ignore syscall cdecl stdcall wen use64 segment procedures on 64bits unix linux machos and defaults to SYSTEMV

Tested and built your HelloWorld got the results for mov rbp, rsp.

This is my test development branch, what's implemented were can change later or not be implemented in the release uasm.
64bits uasm build with windows and ubuntu 18.04
https://github.com/eXOAMP/UASM/releases/download/eX_v2.50_master_alpha0/Uasm_master.7z

With this version can be find the regcall for 32bits and 64bits windows, unix, linux, machos. thiscall for 32bits windows, windows vectorcall for bout 64bits and 32bits (invoke needs work on the implementation).

SYSTEMV
REGCALL
VECTORCALL
THISCALL

Info about Intel regcall https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-c-c-calling-conventions