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

nidud

  • Member
  • *****
  • Posts: 2213
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #225 on: December 14, 2019, 11:53:28 PM »
I updated the source for the 16-bit CRT code. This was to the use of SIZE so I guess the switch /Znk could be used there as well.

Some other changes in addition to : public class is that { is now followed like \

    .data

    ID3D11Texture2D { ; *this
        {             ; .D3D11Buffer
            {         ; ..ID3D11Resource
                {     ; ...ID3D11DeviceChild
                    { ; ....IUnknown
                        0
                    }
                }
            }
        }
    },{
        {{{{1}}}}
    }


Vortex

  • Member
  • *****
  • Posts: 2583
Re: Asmc source and binaries
« Reply #226 on: December 15, 2019, 05:00:13 AM »
Hi nidud,

Thanks for the update. Building the 64-bit version of the runtime library with DosZip, I receive the following error message :
Code: [Select]
Assembling: twindow\tevent.asm
 Assembling: twindow\tresource.asm
 Assembling: twindow\twindow.asm
Error! Unable to open file 'C:\asmc-master\lib\amd64\_wlib872.$$$'. No such file
 or directory.

nidud

  • Member
  • *****
  • Posts: 2213
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #227 on: December 15, 2019, 05:36:46 AM »
Used the batch install and everything worked fine, decompressed it to a temp directory and used DZ to build lib64 and got the same error.

Turns out the ./lib/amd64 directory is missing now after the makefiles was moved out. The import build creates this directory but the LIBC build do not.


nidud

  • Member
  • *****
  • Posts: 2213
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #228 on: December 18, 2019, 12:10:03 AM »
I updated the makefile to create the amd64 directory.

!include srcpath

AFLAGS = -Zi -Zp8 -D_CRTBLD -Cs -I$(inc_dir)

target_path = $(lib_dir)\amd64

$(target_path)\libc.lib: $(target_path)
    asmc64 $(AFLAGS) /r $(src_dir)\lib64\*.asm
    libw /q /b /n /c /fac $@ *.obj
    del *.obj

$(target_path):
    if not exist $(target_path) md $(target_path)

I see the -Zi switch and a full path to the source are added there. This is strictly not needed and adds to the size of LIBC but convenient for x64dbg.

Greenhorn

  • Member
  • **
  • Posts: 175
Re: Asmc source and binaries
« Reply #229 on: December 22, 2019, 11:51:36 PM »
Hi nidud,

asmc 2.31.02 creates some mistakes in my project.

As far as I can see on a quick view it affects every proc that has more than two arguments.
It occurs always at stack preparation that asmc creates wrong code.

Options for assembling the file:
Code: [Select]
option win64:3
option frame:auto
option casemap:none

Command line:
Code: [Select]
asmc64.exe /c /nologo /ws /Sg /Zi /Fo"x64\Debug\%(FileName).obj" /D"WIN32" /D"_WIN64" /D"_DEBUG" /D"_WINDOWS" /D"_UNICODE" /D"UNICODE" /Fl"x64\Debug\%(Filename).lst" /I"D:\Win7Inc\include" /Cp /W2 /win64 /Zp8


This is the output of the listing file:
Code: [Select]
000005CD                        EasyCreateFont proc FRAME, nPointSize:SDWORD, fBold:BOOL, dwQuality:DWORD, szFaceName:LPTSTR

000005CD  48894C2408        *   mov [rsp+8], rcx
000005D2  4889542410        *   mov [rsp+16], rdx
000005D7  4C894C2420        *   mov [rsp+24], r8
000005DC  55                *   mov [rsp+3                                    *   push r000005DD  488BEC                *   .pushreg r                                *   mov rbp, rsp
000005E0  4883EC70          *   .setframe rbp, 0
000005EA                               , 0 + @ReservedStack
                                          k 0 + @ReservedS000005E4                          *   .endprol000005E4  837D1800                  .if (fBold)000005E8  7408                *   cmp (fBold), 0
000005F2                    *   jz  @C0013
000005EA  41BABC020000          mov  r10d, FW_BOLD
000005F0                        .else
000005F0  EB03              *   jmp @C0014
000005F2                    *   @C0013:
000005F2  4D33D2                xor  r10, r10
000005F5                        .endif
000005F5                    *   @C0014:

000005FF                        mov  ecx, PointsToLogical (nPointSize)
000005FF                    *   invoke PointsToLogical,  nPointSize
000005FF                    *    mov ecx, nPointSize
00000602                    *    call PointsToLogical
00000607                    *   mov ecx, eax
00000005FF                    *   invoke CreateFontW,  ecx, 0, 0, 0, r10d000005F5                    FaceName
000005FF  488B4528          *  000005F5  8B4D10       00000603  4889442468        *  000005F8  E885FFFFFF  00000608  C744246000000000  *    000005FD  8BC8             00000610  C744245800000000  *    mov dword ptr [rsp+88], 0
00000618  C744245000000000  *    mov dword ptr [rsp+80], 0
00000620  C744244800000000  *    mov dword ptr [rsp+72], 0
00000628  C744244000000000  *    mov dword ptr [rsp+64], 0
00000630  C744243800000000  *    mov dword ptr [rsp+56], 0
00000638  C744243000000000  *    mov dword ptr [rsp+48], 0
00000640  C744242800000000  *    mov dword ptr [rsp+40], 0
00000648  4489542420        *    mov [rsp+32], r10d
0000064D  4533C9            *    xor r9d, r9d
00000650  4533C0            *    xor r8d, r8d
00000653  33D2              *    xor edx, edx
00000655  E800000000        *    call CreateFontW
                                invoke CreateFontW ( ecx, 0, 0, 0, r10d,0,0,0,0,0,0,0,0,szFaceName)
0000065A                        ret
0000065A  C9                *   leave
0000065B  C3                *   retn
00000078                    *   .xdata segment
00000078  01170305          *   db 1t + (00h shl 3), 28t, 3t, 05h + (00h shl 4)
0000007C  17D213531050      *   dw 0321ch, 05318h, 05015h
00000082  0000              *   align 4
00000084                    *   .xdata ends
00000078                    *   .pdata segment
00000078  000000008F00000078*   dd imagerel EasyCreateFont, imagerel EasyCreateFont+094h, imagerel $xdatasym+078h
00000084                    *   .pdata ends
0000065C                        EasyCreateFont endp

This is the disassembly of the debugger (r8 isn't MOVed to the stack frame):
Code: [Select]
   417: EasyCreateFont proc FRAME, nPointSize:SDWORD, fBold:BOOL, dwQuality:DWORD, szFaceName:LPTSTR
000000013F565EDD  mov         qword ptr [rsp+8],rcx 
000000013F565EE2  mov         qword ptr [rsp+10h],rdx 
000000013F565EE7  mov         qword ptr [rsp+20h],r9 
000000013F565EEC  push        rbp 
000000013F565EED  mov         rbp,rsp 
000000013F565EF0  sub         rsp,70h 
   418:
   419: .if (fBold)
000000013F565EF4  cmp         dword ptr [fBold],0 
000000013F565EF8  je          EasyCreateFont+25h (13F565F02h) 
   420: mov  r10d, FW_BOLD
000000013F565EFA  mov         r10d,2BCh 
   421: .else
000000013F565F00  jmp         EasyCreateFont+28h (13F565F05h) 
   422: xor  r10, r10
000000013F565F02  xor         r10,r10 
   423: .endif
   424:
   425: mov  ecx, PointsToLogical (nPointSize)
000000013F565F05  mov         ecx,dword ptr [nPointSize] 
000000013F565F08  call        PointsToLogical (13F565E92h) 
000000013F565F0D  mov         ecx,eax 
   426:
   427: CreateFont (
   428: ecx,
   429: 0, 0, 0,
   430: r10d,
   431: 0,0,0,0,0,0,0,0,
   432: szFaceName
   433: )
000000013F565F0F  mov         rax,qword ptr [szFaceName] 
000000013F565F13  mov         qword ptr [rsp+68h],rax 
000000013F565F18  mov         dword ptr [rsp+60h],0 
000000013F565F20  mov         dword ptr [rsp+58h],0 
000000013F565F28  mov         dword ptr [rsp+50h],0 
000000013F565F30  mov         dword ptr [rsp+48h],0 
000000013F565F38  mov         dword ptr [rsp+40h],0 
000000013F565F40  mov         dword ptr [rsp+38h],0 
000000013F565F48  mov         dword ptr [rsp+30h],0 
000000013F565F50  mov         dword ptr [rsp+28h],0 
000000013F565F58  mov         dword ptr [rsp+20h],r10d 
000000013F565F5D  xor         r9d,r9d 
000000013F565F60  xor         r8d,r8d 
000000013F565F63  xor         edx,edx 
000000013F565F65  call        CreateFontW (13F5753CCh) 
   434: ret
000000013F565F6A  leave 
000000013F565F6B  ret 

Last tested version without this error is asmc 2.30.01.

Kind regards and merry christmas to all of you
Greenhorn

nidud

  • Member
  • *****
  • Posts: 2213
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #230 on: December 23, 2019, 02:47:06 AM »
Quote
asmc 2.31.02 creates some mistakes in my project.

Last tested version without this error is asmc 2.30.01.

Yes, that's a long time ago so this is optimized: If the argument is not used (dwQuality in this case) then it's not saved to the stack. At best this should only reduce the size of the binary.

Quote
Kind regards and merry christmas to all of you
Greenhorn
Second that so happy holidays folks  :thumbsup:

Greenhorn

  • Member
  • **
  • Posts: 175
Re: Asmc source and binaries
« Reply #231 on: December 24, 2019, 04:50:13 AM »
Thanks for clarification, nidud.

Now the DBG_UNREFERENCED_PARAMETER macro makes some sense to me.   :icon_idea:  :bgrin:
Even if its original purpose slightly differs I can maybe customize it for this purpose.

The background is that e.g. in my custom controls I have a kind of this-pointer to the control's info structure as a parameter in procedures. This is always in RCX parameter and within the procedure I MOVe it directly to e.g. RDI. So the label of this parameter is mostly not used. However, during debugging it is nice to watch the content of the info struct but due to the optimazation the VS debugger doesn't evaluate the pointer anymore.  :sad:

So maybe I can do something like this:

Code: [Select]
DBG_UNREFERENCED_PARAMETER macro p:REQ
ifdef _DEBUG
;-- TODO: work out which register to move to the stack frame (RCX, RDX, R8 or R9)
mov  [RSP+8], rcx
else
exitm <>
endif
endm


By the way I noticed another strange behaviour. In an .elseif condition some equates/macros are not fully expanded, e.g. if it is as the following:

Code: [Select]
    .686
    .model flat, c
    option  dllimport:<msvcrt>
    option  dllimport:NONE


_HRESULT_TYPEDEF_ macro val
exitm <val >
endm

E_OUTOFMEMORY EQU _HRESULT_TYPEDEF_ ( 8007000Eh )

    .code

main proc
local a: DWORD
.if (a == E_OUTOFMEMORY)
  xor eax, eax ;-- OK!
.endif
.if (a == 0)
xor eax, eax
.elseif (a == E_OUTOFMEMORY)
  xor eax, eax ;-- ERROR A2148 !
.else
.if (a == E_OUTOFMEMORY)
xor eax, eax ;-- OK!
.endif
.endif
    ret
main endp
    end main
Code: [Select]
; Assembling: test.asm
;test.asm(22) : error A2148: invalid symbol type in expression : _HRESULT_TYPEDEF

And finally I have a very last question to you (promised).

Sometimes I can do things like this:
Code: [Select]
LOCAL col:    COLORREF

mov  col, GetPixel (hdc, x, y)

But sometimes it doesn't work and I get an error about different sizes (4 - 8). So sometimes asmc assumes EAX as return value and sometimes it does RAX.
So is returning eax done by accident or can I control it in some way.

Kind regards
Greenhorn

Edit: Typo   :rolleyes:

p.s.: Thanks a lot for your patience and for keeping the ASMC project up !

Greenhorn

  • Member
  • **
  • Posts: 175
Re: Asmc source and binaries
« Reply #232 on: December 24, 2019, 05:56:25 AM »
Sorry, but I have to disturb one more time.

.for ( ... ) .endw will not throw an error but should.


Kind regards
Greenhorn

nidud

  • Member
  • *****
  • Posts: 2213
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #233 on: December 24, 2019, 07:59:26 AM »
Well, looking at the first one the original version seems to touch the parameter and thus force it onto the stack.

#define DBG_UNREFERENCED_PARAMETER(P) { (P) = (P); }

The same logic also work here. Maybe the debugger picks up on the dummy move or you may use CMP P,0. As long as the parameter get used the assembler will sort out the register.

DBG_UNREFERENCED_PARAMETER macro P
ifdef _DEBUG
    exitm<mov P,P>
else
    exitm<>
endif
    endm

nidud

  • Member
  • *****
  • Posts: 2213
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #234 on: December 24, 2019, 08:30:34 AM »
Quote
By the way I noticed another strange behaviour. In an .elseif condition some equates/macros are not fully expanded, e.g. if it is as the following:

Yes, same as this:

    .while eax == E_OUTOFMEMORY
        nop
    .endw

Expansion of function calls and macros are delayed there so it get inserted at the correct location. This assumes code expansion so text macros are probably skipped there. I have to look into that.

Quote
.for ( ... ) .endw will not throw an error but should.

Admittedly I have converted a few .WHILE loops without changing this so I'm sort of aware of the problem but haven't get around fixing it yet.

nidud

  • Member
  • *****
  • Posts: 2213
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #235 on: December 24, 2019, 09:11:00 AM »
Sometimes I can do things like this:
Code: [Select]
LOCAL col:    COLORREF

mov  col, GetPixel (hdc, x, y)

But sometimes it doesn't work and I get an error about different sizes (4 - 8). So sometimes asmc assumes EAX as return value and sometimes it does RAX.
So is returning eax done by accident or can I control it in some way.

You basically control it on the receiving end so it adapt to the size if it is in range and power of 2. The latter was fixed in INVOKE for size 3, 5, 6, and 7 some time ago.

The regression test:

;
; Return value adaptation:
;
; Nested function calls adapts to argument size.
; Assigned values adapts to target size if possible,
; else default is used ([R|E]AX).
;
    .x64
    .model flat, fastcall
    .code

id1  label byte
id2  label word
id4  label dword
id8  label qword
id16 label oword
f4   label real4
f8   label real8
f16  label real16

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()
    movss   f4,   foo()
    movsd   f8,   foo()
    movups  f16,  foo()

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

    bar(bar(xmm0, xmm1), xmm1)

    end

Greenhorn

  • Member
  • **
  • Posts: 175
Re: Asmc source and binaries
« Reply #236 on: December 25, 2019, 09:01:04 AM »
Hi nidud,

in most cases it works fine but here I got the error again (and I get it always at this position):
Code: [Select]
;//
;// Create the control structure
;//
UspAllocate _PROC FRAME uses rbx

LOCAL uspData: ptr USPDATA

mov rbx, malloc (sizeof (USPDATA))
mov uspData, rax

.if (rbx)
;// set all members to zero including run-counts etc
ZeroMemory (rbx, sizeof (USPDATA))

mov [rbx].USPDATA.selFG, GetSysColor (COLOR_HIGHLIGHTTEXT)
mov [rbx].USPDATA.selBG, GetSysColor (COLOR_HIGHLIGHT)
.endif

mov rax, rbx
UspAllocate _ENDP
Members defined in USPDATA struct:
Code: [Select]
;// colours of the selection-highlight
selFG COLORREF ?
selBG COLORREF ?
Output:
Code: [Select]
1>------ Erstellen gestartet: Projekt: UspLib, Konfiguration: Debug x64 ------
1>  Assembling UspLib.asm ...
1>UspLib.asm(1086): error A2022: instruction operands must be the same size : 4 - 8
1>UspLib.asm(1087): error A2022: instruction operands must be the same size : 4 - 8
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\BuildCustomizations\asmc.targets(49,5): error MSB3721: Der Befehl "asmc64.exe /c /ws /Sa /Sg /Zi /Fo"x64\Debug\UspLib.obj" /D"WIN32" /D"_WIN64" /D"_DEBUG" /D"_WINDOWS" /D"_UNICODE" /D"UNICODE" /Fl"x64\Debug\UspLib.lst" /I"D:\Win7Inc\include" /Cp /W2 /win64 /Zp8   UspLib.asm" wurde mit Code 1 beendet.
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 ├╝bersprungen ==========

But for now ... it's holidays.

Kind regards
Greenhorn

Greenhorn

  • Member
  • **
  • Posts: 175
Re: Asmc source and binaries
« Reply #237 on: December 25, 2019, 09:59:11 AM »
Same here:
Code: [Select]
;// change the background if the line is too long
TextEdit@CheckStyle (rdi, TXS_LONGLINES)
mov  edx, [rdi].TEXTEDIT.m_nLongLineLimit
mov  rcx, nColumn
.if (dword ptr [rcx] >= edx && eax)

mov  [rsi].ATTR.fg, TextEdit@GetColour (rdi, TXC_FOREGROUND)
mov  [rsi].ATTR.bg, TextEdit@LongColour (rdi, nLineNo)
.else
TextEdit@GetColour (rdi, TXC_FOREGROUND)
mov  [rsi].ATTR.fg, eax
TextEdit@LineColour (rdi, nLineNo );//GetColour (TXC_BACKGROUND) ;
mov  [rsi].ATTR.bg, eax
.endif
Output:
Code: [Select]
1>------ Erstellen gestartet: Projekt: TextEdit, Konfiguration: Debug x64 ------
1>  Assembling TextPaint.asm ...
1>TextPaint.asm(697): error A2022: instruction operands must be the same size : 4 - 8
1>TextPaint.asm(699): error A2022: instruction operands must be the same size : 4 - 8
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\BuildCustomizations\asmc.targets(49,5): error MSB3721: Der Befehl "asmc64.exe /c /ws /Sg /Zi /Fo"x64\Debug\TextPaint.obj" /D"WIN32" /D"_WIN64" /D"_DEBUG" /D"_WINDOWS" /D"_UNICODE" /D"UNICODE" /Fl"x64\Debug\TextPaint.lst" /I"D:\Win7Inc\include" /Cp /W2 /win64 /Zp8   TextPaint.asm" wurde mit Code 1 beendet.
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 ├╝bersprungen ==========

Could it be that this occurs if the r/eax register is assigned to a struct member ?

Greenhorn

  • Member
  • **
  • Posts: 175
Re: Asmc source and binaries
« Reply #238 on: December 26, 2019, 04:18:20 AM »
It seems to me that it happens on addressing variables via  register:

Code: [Select]
    .x64
    .model flat, fastcall
    option  dllimport:<msvcrt>
    option  dllimport:NONE


RECT struct
left SDWORD ?
top SDWORD ?
right SDWORD ?
bottom SDWORD ?
RECT ends
LPRECT typedef ptr RECT

    .code

foo proc
    ret
foo endp

bar proc f:ptr RECT, b:DWORD
local a: DWORD

mov  [rcx].RECT.left, foo ( ) ;-- error
lea  rax, a
mov  dword ptr [rax], foo ( ) ;-- error
mov  a, foo ( ) ;-- OK
mov  b, foo ( ) ;-- OK
    ret
bar endp

main proc
local rc: RECT
bar (0, &rc)
    ret
main endp
    end main

MOV  b, foo() works in this example but sometimes I also get the error with assigning to proc parameters.

nidud

  • Member
  • *****
  • Posts: 2213
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #239 on: December 26, 2019, 09:25:54 AM »
Added an update.

The stack in SystemV was wrong in case > 8 xmm registers was used. In case xmm16..31 VMOVQ will handle the stack parameters but the encoding was wrong for VMOVQ rax,xmm so this is now fixed.

The MOV DWORD PTR [reg], foo() / MOV [reg].RECT.left, foo() and the .FOR .. .ENDW issue is also fixed.

Regress:

    vr struc
    z1 db ?
    z2 dw ?
    z4 dd ?
    z8 dq ?
    vr ends

foo proc
    ret
foo endp

main proc

    mov byte ptr [rbx],  foo()
    mov word ptr [rbx],  foo()
    mov dword ptr [rbx], foo()

    mov [rbx].vr.z1, foo()
    mov [rbx].vr.z2, foo()
    mov [rbx].vr.z4, foo()
    mov [rbx].vr.z8, foo()
    ret

main endp