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

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #60 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

AssemblyChallenge

  • Member
  • **
  • Posts: 110
Re: Asmc source and binaries
« Reply #61 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.

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #62 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.

AssemblyChallenge

  • Member
  • **
  • Posts: 110
Re: Asmc source and binaries
« Reply #63 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:

AssemblyChallenge

  • Member
  • **
  • Posts: 110
Re: Asmc source and binaries
« Reply #64 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.

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #65 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

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #66 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   

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #67 on: April 07, 2018, 02:39:27 AM »
Added more include files for D3D10/11.

A simple test case for D3D11CreateDevice():
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

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #68 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 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.

Greenhorn

  • Member
  • **
  • Posts: 98
Re: Asmc source and binaries
« Reply #69 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
  • MAKEWPARAM    (missing macro MAKE(L)ONG)
  • MAKELPARAM   (missing macro MAKE(L)ONG)
  • MAKELRESULT   (missing macro MAKE(L)ONG)
windef.inc    (min/max deactivated by condition NOMINMAX, remaining macros are missing)
  • min
  • max
  • MAKEWORD
  • MAKELONG
  • LOWORD
  • HIWORD
  • LOBYTE
  • HIBYTE
stdlib.inc    (macros are not included here)
  • min/__min
  • max/__max


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

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #70 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.

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #71 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))

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #72 on: May 11, 2018, 01:16:11 AM »
Added CREF(push/pop) to the .PRAGMA directive for .cref/.nocref.

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #73 on: May 12, 2018, 06:13:03 AM »
Small Windows include update.

Added one more COM sample using IShellLink from Raymond Chen.

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

nidud

  • Member
  • *****
  • Posts: 1510
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #74 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.