Author Topic: Asmc source and binaries  (Read 31524 times)

nidud

  • Member
  • *****
  • Posts: 1800
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #165 on: March 17, 2019, 02:15:25 AM »
 :biggrin:

These bad things end up on his desk (not yours) so I do understand his point of view in that regard, hence the You’re not off by yourself; you’re part of a society part.

The unwind information do not add any changes to the procedure. It only writes a binary description of the prologue in order to enable the system to unwind the stack. This is part of the ABI for x64. You only need to use the FRAME directive and set OPTION FRAME:AUTO in order to add the unwind information (now also handle CSTACK):

    .code

    option cstack:on, frame:auto

foo proc frame uses rsi rdi rbx a:byte

    ret

foo endp

    end

Code produced:

        push    rsi
        push    rdi
        push    rbx
        push    rbp
        mov     rbp, rsp
        sub     rsp, 8
        leave           
        pop     rbx     
        pop     rdi     
        pop     rsi
        ret       

Added information:

        .pushreg rsi
        .pushreg rdi
        .pushreg rbx
        .pushreg rbp
        .setframe rbp, 0
        .allocstack 8
        .endprolog
« Last Edit: March 17, 2019, 03:29:21 AM by nidud »

nidud

  • Member
  • *****
  • Posts: 1800
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #166 on: March 25, 2019, 07:29:36 AM »
Added a new release: https://github.com/nidud/asmc/releases

Only small changes but the source wont assemble with the current binaries, mostly related to parsing header files. One of the issues was using the header for dynamic linking using msvcrt.dll with linkw. The default setting was either using the -pe switch or linkw + libc.

Some new pragma directives added:

- .pragma warning(push)
- .pragma warning(pop)
- .pragma(warning(disable: <num>))
- .pragma comment(lib, "name.lib"[, "name2.lib"])

.pragma comment(lib, libc, msvcrt) will expand as follows:

ifdef __PE__
option dllimport:<msvcrt>
elseifdef _MSVCRT
includelib msvcrt.lib
else
includelib libc.lib
endif


The pragma init and exit directives now use the same segments as VC. The record size is equal in both 32 and 64-bit (8 bytes) where the first DWORD is the function address and the next priority. This means the 64-bit record holds a relative address from ImageBase. They are read-only records (CONST) and may now be reused as appose to the old version where records was cleared after use.

.CRT$XI0 CONST .rdata 0043a000 00000008
.CRT$XIA CONST .rdata 0043a008 00000030
.CRT$XIZ CONST .rdata 0043a038 00000008
.CRT$XT0 CONST .rdata 0043a040 00000008
.CRT$XTA CONST .rdata 0043a048 00000020
.CRT$XTZ CONST .rdata 0043a068 00000008

Init records are added to XIA and terminators to XTA.

The 64-bit version of LINK provides a global symbol __ImageBase which enable direct calculation of an address. This may be achieved by using a macro above the main module. The live version is GetImageBase().

include stdio.inc
include winbase.inc

DeclImageBase

main proc

    printf("GetImageBase(): %p\n", GetImageBase())
    printf("&__ImageBase:   %p\n", &__ImageBase)
    ret

main endp

    end

GetImageBase(): 0000000000400000
&__ImageBase:   0000000000400000

nidud

  • Member
  • *****
  • Posts: 1800
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #167 on: March 26, 2019, 06:52:37 AM »
Added switch /Ge - force stack checking for all funcs

This emit a conditional _chkstk() inside the prologue if stack space that is to be allocated exceeds 1000h bytes. Note that the 32-bit version of _chkstk() actually set ESP but the 64-bit version only probe the stack. The argument (size) is passed in AX so the latter version needs a SUB RSP,RAX after the call.

Test case:
https://github.com/nidud/asmc/tree/master/source/test/chkstk

This from the test case provided by Manos for pcc32:
http://masm32.com/board/index.php?topic=7762.msg85094#msg85094

I also had to update some of the time functions and types in order to make this work so a rebuild of libc is needed to run the sample.

foo proc

  local big[50000]:byte

    ...


nidud

  • Member
  • *****
  • Posts: 1800
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #168 on: March 28, 2019, 05:46:14 AM »
Added some changes with regard to the issue discussed here:
http://masm32.com/board/index.php?topic=7770.msg85118#msg85118

Problem is you can't move overlapped values from memory without this blowing up at some point. Same problem as the memcpy() thing pointed out by rrr where unaligned overlapped values was moved to xmm registers. This implies you actually need to know the argument size before loading a register from memory.

In 32-bit the size is limited to 1,2,3,4, so the only odd value is 3.

This will blow up if you push a dword:
Code: [Select]
include winbase.inc
include tchar.inc

    MS3 struct
    _0  db ?
    _1  db ?
    _2  db ?
    MS3 ends

    .code

dummy proc ms:MS3
    ret
dummy endp

main proc

    .if VirtualAlloc(0, 4096, MEM_COMMIT, PAGE_READWRITE)

        mov esi,eax

        dummy([esi+4096-sizeof(MS3)])
        VirtualFree(esi, 0, MEM_RELEASE)
    .endif
    ret

main endp

    end _tstart

*    mov al, byte ptr [esi + 4096 - sizeof( MS3)][2]
*    shl eax,16
*    mov ax, word ptr [esi + 4096 - sizeof( MS3)]
*    push eax


In 64-bit you have 5, 6, and 7 in addition to 3 but normal sizes also have to correspond to argument size. If the argument size is 1, 2, or 4, loading RCX from memory will potentiality overlap with 7, 6, or 4 bytes into a protected area:

    mov rcx, qword ptr m1/2/3/4/5/6/7

The error message from this is now removed:

    foo proto :byte, :word, :dword, :ptr
    ...
    foo([rdi], [rdi], [rdi], [rdi])

*    mov cl, [rdi]
*    mov dx, [rdi]
*    mov r8d, [rdi]
*    mov r9, [rdi]

nidud

  • Member
  • *****
  • Posts: 1800
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #169 on: April 17, 2019, 06:01:34 AM »
Made some changes to 64-bit fastcall and vectorcall: load args right to left.

This now works:
    p5(rcx,rdx,r8, r9, 0   )
    p5(0,  rcx,rdx,r8, r9  )
    p5(0,  0,  rcx,rdx,r8  )
    p5(0,  0,  0,  rcx,rdx )
    p5(0,  0,  0,  0,  rcx )

This fails:
    p5(rdx,r8, r9, 0,  0   )
    p5(r8, r9, 0,  0,  0   )
    p5(r9, 0,  0,  0,  0   )

nidud

  • Member
  • *****
  • Posts: 1800
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #170 on: April 17, 2019, 08:44:11 AM »
Renamed some directives to dot names:

    .NAME
    .TITLE
    .PAGE
    .SUBTITLE
    .SUBTTL

Names like SIZE, LENGTH, THIS, and TYPE are also irritating but used more often than the list directives above...

jj2007

  • Member
  • *****
  • Posts: 9801
  • Assembler is fun ;-)
    • MasmBasic
Re: Asmc source and binaries
« Reply #171 on: April 17, 2019, 10:35:36 AM »
Source and binaries for Asmc is now available at GitHub:

https://github.com/nidud/asmc

Hi Nidud,

I just wanted to updated and test my old September 2018 version of AsmC but can't find the exe on Github. Where exactly is the zip that contains AsmC.exe?

TimoVJL

  • Member
  • ***
  • Posts: 476
Re: Asmc source and binaries
« Reply #172 on: April 17, 2019, 11:02:19 AM »
May the source be with you

jj2007

  • Member
  • *****
  • Posts: 9801
  • Assembler is fun ;-)
    • MasmBasic
Re: Asmc source and binaries
« Reply #173 on: April 17, 2019, 11:19:45 AM »
Thanks, Timo :icon14:

nidud

  • Member
  • *****
  • Posts: 1800
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #174 on: April 19, 2019, 02:11:21 AM »
Gone a bit berserk on these names so here's a test version which renames the following directives and operators:

    c           ccall
    name        .name
    page        .page
    subtitle    .subtitle
    subttl      .subttl
    title       .title
    low         .low
    high        .high
    size        .size
    length      .length
    this        .this
    mask        .mask
    width       .width
    type        typeof

C is still valid for proc, proto, .model, and option language but it's not a public symbol anymore. As for testing the main problem was the use of SIZE which could all be replaced by SIZEOF. Macros used TYPE a lot but other than that no problems.

jj2007

  • Member
  • *****
  • Posts: 9801
  • Assembler is fun ;-)
    • MasmBasic
Re: Asmc source and binaries
« Reply #175 on: April 19, 2019, 02:26:54 AM »
Certainly innovative, but it will break a lot of existing code :badgrin:
Code: [Select]
*** Assemble using AsmC  ***
 Assembling: tmp_file.asm
*** MasmBasic version 16.04.2019 ***
tmp_file.asm(2054) : error A2006: undefined symbol : type

Another source:
Code: [Select]
Assembling: C:\Masm32\MasmBasic\libtmpAA.asm
 Assembling: C:\Masm32\MasmBasic\libtmpAB.asm
 Assembling: C:\Masm32\MasmBasic\libtmpAC.asm
C:\Masm32\MasmBasic\libtmpAC.asm(1289) : error A2006: undefined symbol : type
 Let(111)[MasmBasic.inc]: Macro called from
  Cat$(9)[MasmBasic.inc]: Macro called from
   C:\Masm32\MasmBasic\libtmpAC.asm(1289): Main line code
C:\Masm32\MasmBasic\libtmpAC.asm(1289) : error A2006: undefined symbol : type
 PushString(107)[MasmBasic.inc]: Macro called from
  MacroLoop(30): iteration 1: Macro called from
   Let(172)[MasmBasic.inc]: Macro called from
    Cat$(9)[MasmBasic.inc]: Macro called from
     C:\Masm32\MasmBasic\libtmpAC.asm(1289): Main line code
C:\Masm32\MasmBasic\libtmpAC.asm(1289) : error A2006: undefined symbol : type
 PushString(107)[MasmBasic.inc]: Macro called from
  MacroLoop(30): iteration 2: Macro called from
   Let(172)[MasmBasic.inc]: Macro called from
    Cat$(9)[MasmBasic.inc]: Macro called from
     C:\Masm32\MasmBasic\libtmpAC.asm(1289): Main line code
C:\Masm32\MasmBasic\libtmpAC.asm(1289) : error A2006: undefined symbol : type
 PushString(107)[MasmBasic.inc]: Macro called from
  MacroLoop(30): iteration 3: Macro called from
   Let(172)[MasmBasic.inc]: Macro called from
    Cat$(9)[MasmBasic.inc]: Macro called from
     C:\Masm32\MasmBasic\libtmpAC.asm(1289): Main line code
C:\Masm32\MasmBasic\libtmpAC.asm(1289) : error A2006: undefined symbol : type
 PushString(107)[MasmBasic.inc]: Macro called from
  MacroLoop(30): iteration 4: Macro called from
   Let(172)[MasmBasic.inc]: Macro called from
    Cat$(9)[MasmBasic.inc]: Macro called from
     C:\Masm32\MasmBasic\libtmpAC.asm(1289): Main line code
C:\Masm32\MasmBasic\libtmpAC.asm(1289) : error A2006: undefined symbol : type
 PushString(107)[MasmBasic.inc]: Macro called from
  MacroLoop(30): iteration 6: Macro called from
   Let(172)[MasmBasic.inc]: Macro called from
    Cat$(9)[MasmBasic.inc]: Macro called from
     C:\Masm32\MasmBasic\libtmpAC.asm(1289): Main line code
C:\Masm32\MasmBasic\libtmpAC.asm(1289) : error A2006: undefined symbol : type
 PushString(107)[MasmBasic.inc]: Macro called from
  MacroLoop(30): iteration 7: Macro called from
   Let(172)[MasmBasic.inc]: Macro called from
    Cat$(9)[MasmBasic.inc]: Macro called from
     C:\Masm32\MasmBasic\libtmpAC.asm(1289): Main line code

....
\masm32\MasmBasic\TestMasmBasic.asm(87) : error A2006: undefined symbol : type
 ChkNum(46)[MasmBasic.inc]: Macro called from
  MacroLoop(116): iteration 1: Macro called from
   Str$(250)[MasmBasic.inc]: Macro called from
    wStr$(2)[MasmBasic.inc]: Macro called from
     \masm32\MasmBasic\TestMasmBasic.asm(87): Included by
      tmp_file.asm(2): Main line code
\masm32\MasmBasic\TestMasmBasic.asm(87) : error A2006: undefined symbol : type
 ChkNum(49)[MasmBasic.inc]: Macro called from
  MacroLoop(116): iteration 1: Macro called from
   Str$(250)[MasmBasic.inc]: Macro called from
    wStr$(2)[MasmBasic.inc]: Macro called from
     \masm32\MasmBasic\TestMasmBasic.asm(87): Included by
      tmp_file.asm(2): Main line code
\masm32\MasmBasic\TestMasmBasic.asm(87) : error A2006: undefined symbol : type
 ChkNum(52)[MasmBasic.inc]: Macro called from
  MacroLoop(116): iteration 1: Macro called from
   Str$(250)[MasmBasic.inc]: Macro called from
    wStr$(2)[MasmBasic.inc]: Macro called from
     \masm32\MasmBasic\TestMasmBasic.asm(87): Included by
      tmp_file.asm(2): Main line code
unknown type: RECT.left
\masm32\MasmBasic\TestMasmBasic.asm(87) : error A2084: constant value too large
 Str$(269)[MasmBasic.inc]: Macro called from
  wStr$(2)[MasmBasic.inc]: Macro called from
   \masm32\MasmBasic\TestMasmBasic.asm(87): Included by
    tmp_file.asm(2): Main line code
\masm32\MasmBasic\TestMasmBasic.asm(87) : error A2006: undefined symbol : type
 ChkNum(36)[MasmBasic.inc]: Macro called from
  MacroLoop(116): iteration 1: Macro called from
   Str$(250)[MasmBasic.inc]: Macro called from
    wStr$(2)[MasmBasic.inc]: Macro called from
     \masm32\MasmBasic\TestMasmBasic.asm(87): Included by
      tmp_file.asm(2): Main line code
\masm32\MasmBasic\TestMasmBasic.asm(87) : error A2006: undefined symbol : type
\masm32\MasmBasic\TestMasmBasic.asm(87) : fatal error A1012: error count exceeds 100; stopping assembly
*** Assembly Error ***

Even the forum complains:
Code: [Select]
The following error or errors occurred while posting this message:
The message exceeds the maximum allowed length (20000 characters)

No idea what these mean, though:
Code: [Select]
unknown type: RECT.left
## Invalid type of [esi.MbT2-MbT2].LViewItem.stateMask ##
## Invalid type of hGui ##
## Invalid type of MbSpriteTable[-4] ##

nidud

  • Member
  • *****
  • Posts: 1800
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #176 on: April 19, 2019, 03:46:05 AM »
Try the compatible switch and see if that works:
/Zne   -- Disable non Masm extensions.

You may then try this and (if it works) disable one by one to see whats used.

ifdef __ASMC__
    name        equ <.name>
    page        equ <.page>
    subtitle    equ <.subtitle>
    subttl      equ <.subttl>
    title       equ <.title>
    low         equ <.low>
    high        equ <.high>
    size        equ <.size>
    length      equ <.length>
    this        equ <.this>
    mask        equ <.mask>
    width       equ <.width>
type macro arg
    exitm<typeof(arg)>
    endm
endif

jj2007

  • Member
  • *****
  • Posts: 9801
  • Assembler is fun ;-)
    • MasmBasic
Re: Asmc source and binaries
« Reply #177 on: April 19, 2019, 05:06:12 AM »
Try the compatible switch and see if that works:
/Zne   -- Disable non Masm extensions.

Features that break loads of existing code should be disabled by default. If not, you force the coder to use assembler-specific options, which is about as ugly as environment variables. For example, /Zne is needed for the new AsmC version but triggers an error when assembling with UAsm :redface:

With /Zne, I get error A2008: syntax error : equ <OWORD>

Code: [Select]
ifndef REAL16
  REAL16 equ <OWORD>
endif

That can be "healed", of course:
Code: [Select]
ifndef REAL16
ifndef __ASMC__
REAL16 equ <OWORD>
endif
endif

Nonetheless, the assembler should take a clear stand on this: Either REAL16 is defined, then it should skip the EQU line, or it's not - and then it's just an equate. The current behaviour is clearly inconsistent. Probably a feature 8)

So, /Zne works a little bit, at least for the RichMasm source. For my macro-heavy library even that fails miserably, with loads of "type" errors (it builds fine with ML 6.15, ML 10.0 and UAsm).
« Last Edit: April 19, 2019, 06:30:19 AM by jj2007 »

nidud

  • Member
  • *****
  • Posts: 1800
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #178 on: April 20, 2019, 12:09:40 AM »
Features that break loads of existing code should be disabled by default.

Maintaining (fixing bugs) versus development. The latter will in most cases brake existing code but given the old version used is still available this is not a problem. This happens from time to time, like the Masm /Zm switch for instance. There's currently 4 of these:

    -Zm     Enable MASM 5.10 compatibility
    -Zg     Generate code to match Masm
    -Zne    Disable non Masm extensions
    -Xc     Disable Asmc extensions

The switch -Xc and the OPTION ASMC will be removed.

Quote
With /Zne, I get error A2008: syntax error : equ <OWORD>

Code: [Select]
ifndef REAL16
  REAL16 equ <OWORD>
endif

That can be "healed", of course:
Code: [Select]
ifndef REAL16
ifndef __ASMC__
REAL16 equ <OWORD>
endif
endif

Nonetheless, the assembler should take a clear stand on this: Either REAL16 is defined, then it should skip the EQU line, or it's not - and then it's just an equate. The current behaviour is clearly inconsistent. Probably a feature 8)

Masm will reject using IF this way but Asmc will allow this unless the /Zne switch is used.

ifndef DWORD -- warning A8005: IF[n]DEF expects a plain symbol as argument : ifndef DWORD

Masm 6.14:

ifdef DWORD
REAL16 equ <DWORD>
endif
mov eax,REAL16 -- error A2006: undefined symbol : REAL16
« Last Edit: April 20, 2019, 01:10:23 AM by nidud »

jj2007

  • Member
  • *****
  • Posts: 9801
  • Assembler is fun ;-)
    • MasmBasic
Re: Asmc source and binaries
« Reply #179 on: April 20, 2019, 01:15:51 AM »
Nidud,

I am a fan of AsmC (and of UAsm), you should know that. If I see loads of error messages, I make an effort to find a workaround, and often I find one with my decades of expertise.

Now imagine what will be the reaction of somebody exploring (without being already a fan) whether AsmC would be a valid replacement for his recent buggy ML.exe versions. Imagine what that person thinks when seeing endless error messages. This is why features that can and do break existing code should be disabled by default. Fortunately I kept version 23 March 2019, which works perfectly.