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

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #285 on: March 30, 2021, 10:55:01 PM »
Added another layer to local assignment.

It handles single structures and arrays of regular types but failed on arrays of structures.

    .new points[4]:POINT = {
        {  20,  40 },
        { 320, 200 },
        { 330, 110 },
        { 450,  40 } }

    *    mov points[0].x,20
    *    mov points[0].y,40
    *    mov points[8].x,320
    *    mov points[8].y,200
    *    mov points[16].x,330
    *    mov points[16].y,110
    *    mov points[24].x,450
    *    mov points[24].y,40

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #286 on: March 31, 2021, 01:09:16 AM »
Added directive .INLINE and changed the typeid() macro.

typeid is now a pure text macro for upper(types) and an optional pre-text string.

.inline types a:abs, b:abs, c:abs {
%   typeid(a)typeid(b)typeid(c)(a, b, c)
%   typeid(func_,a)typeid(_,b)typeid(_,c)(a, b, c)
    }
...
  local a:ptr sbyte, b:RECT, c:qword

    types(a, b, c)

    * PSBYTERECTQWORD(a, b, c)
    * func_PSBYTE_RECT_QWORD(a, b, c)

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #287 on: April 03, 2021, 09:18:53 AM »
Another round for local assignment.

In case of function calls a comma may occur between each assignment within brackets, and quoted text may be Unicode (L"text").

        .new wcex:WNDCLASSEX = {
            sizeof(wcex),
            CS_HREDRAW or CS_VREDRAW,
            &WndProc,
            sizeof(LONG_PTR),
            hInstance,
            LoadIcon(NULL, IDI_APPLICATION),
            LoadIcon(NULL, IDI_APPLICATION),
            LoadCursor(NULL, IDC_ARROW),
            0,
            0,
            L"DesktopToastsApp",
            LoadIcon(NULL, IDI_APPLICATION)
            }

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #288 on: April 03, 2021, 09:36:20 AM »
Added stack cleanup for 32-bit inline functions.

Static members shifts arguments to the right as the class (this) is passed as reference. Only fastcall can be used as inline functions (FASTCALL/WATCALL) in 32-bit, so this limits the number of register arguments.

.template wt watcall

    atom byte ?

    .static a a:byte {
        mov this.atom,a ; al
        }
    .static b a:byte, b:byte, c:byte, d:byte {
        mov this.atom,a ; al
        mov this.atom,b ; dl
        mov this.atom,c ; bl
        mov this.atom,d ; cl
        }
    .ends

.template ft fastcall

    atom byte ?

    .static a a:byte {
        mov this.atom,a ; cl
        }
    .static b a:byte, b:byte, c:byte, d:byte {
        mov this.atom,a ; cl
        mov this.atom,b ; dl
        mov this.atom,c ; [esp+0*4]
        mov this.atom,d ; [esp+1*4]
        ;   add esp, 8
        }
    .ends

Watcall uses 4 registers and the rest are pushed on the stack.

.inline w6 watcall a1:dword, a2:dword, a3:dword, a4:dword, a5:dword, a6:dword {
    mov edi,a1 ; eax
    mov edi,a2 ; edx
    mov edi,a3 ; ebx
    mov edi,a4 ; ecx
    mov edi,a5 ; [esp+0*4]
    mov edi,a6 ; [esp+1*4]
;   add esp, 8
    }

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #289 on: April 05, 2021, 07:36:10 AM »
Another console example, more or less copied as is. Using memory operands if possible and the Masm register definition for 32/64 bit. It needs Unicode so the /ws option is needed.

asmc -pe -ws ResolveName.asm
asmc64 -pe -ws ResolveName.asm

Code: [Select]
;;
;; https://github.com/microsoft/Windows-classic-samples
;;
;; Abstract:
;;
;;     The sample demonstrates how to use asynchronous GetAddrInfoEx to
;;     resolve name to IP address.
;;
;;     ResolveName <QueryName>
;;
;;

include windows.inc
include stdio.inc
include Ws2tcpip.inc
include tchar.inc

option dllimport:none

MAX_ADDRESS_STRING_LENGTH equ 64

;;
;;  Asynchronous query context structure.
;;

QUERY_CONTEXT   STRUC
QueryOverlapped OVERLAPPED <>
QueryResults    PADDRINFOEX ?
CompleteEvent   HANDLE ?
QUERY_CONTEXT   ENDS
PQUERY_CONTEXT  typedef ptr QUERY_CONTEXT

QueryCompleteCallback proto private \
    Error: DWORD,
    Bytes: DWORD,
    Overlapped: LPOVERLAPPED

    .code

_tmain proc \
    Argc: int_t,
    Argv: ptr PWCHAR


    .new Error:SINT = ERROR_SUCCESS
    .new wsaData:WSADATA
    .new IsWSAStartupCalled:BOOL = FALSE
    .new Hints:ADDRINFOEX = {0}
    .new QueryContext:QUERY_CONTEXT = {0}
    .new CancelHandle:HANDLE = NULL
    .new QueryTimeout:DWORD = 5 * 1000 ;; 5 seconds

    ;;
    ;;  Validate the parameters
    ;;

    .if (Argc != 2)

        _tprintf("Usage: ResolveName <QueryName>\n")
        jmp done
    .endif

    ;;
    ;;  All Winsock functions require WSAStartup() to be called first
    ;;

    mov Error,WSAStartup(MAKEWORD(2, 2), &wsaData)
    .if (Error != 0)

        _tprintf("WSAStartup failed with %d\n", Error)
        jmp done
    .endif

    mov IsWSAStartupCalled,TRUE

    mov Hints.ai_family,AF_UNSPEC

    ;;
    ;;  Note that this is a simple sample that waits/cancels a single
    ;;  asynchronous query. The reader may extend this to support
    ;;  multiple asynchronous queries.
    ;;

    mov QueryContext.CompleteEvent,CreateEvent(NULL, TRUE, FALSE, NULL)

    .if (QueryContext.CompleteEvent == NULL)

        mov Error,GetLastError()
        _tprintf("Failed to create completion event: Error %d\n",  Error)
        jmp done
    .endif

    ;;
    ;;  Initiate asynchronous GetAddrInfoExW.
    ;;
    ;;  Note GetAddrInfoEx can also be invoked asynchronously using an event
    ;;  in the overlapped object (Just set hEvent in the Overlapped object
    ;;  and set NULL as completion callback.)
    ;;
    ;;  This sample uses the completion callback method.
    ;;

    mov rcx,Argv
    mov Error,GetAddrInfoEx([rcx+size_t],
                           NULL,
                           NS_DNS,
                           NULL,
                           &Hints,
                           &QueryContext.QueryResults,
                           NULL,
                           &QueryContext.QueryOverlapped,
                           &QueryCompleteCallback,
                           &CancelHandle)

    ;;
    ;;  If GetAddrInfoExW() returns  WSA_IO_PENDING, GetAddrInfoExW will invoke
    ;;  the completion routine. If GetAddrInfoExW returned anything else we must
    ;;  invoke the completion directly.
    ;;

    .if (Error != WSA_IO_PENDING)

        QueryCompleteCallback(Error, 0, &QueryContext.QueryOverlapped)
        jmp done
    .endif

    ;;
    ;;  Wait for query completion for 5 seconds and cancel the query if it has
    ;;  not yet completed.
    ;;

    .if (WaitForSingleObject(QueryContext.CompleteEvent,
                            QueryTimeout)  == WAIT_TIMEOUT )


        ;;
        ;;  Cancel the query: Note that the GetAddrInfoExCancelcancel call does
        ;;  not block, so we must wait for the completion routine to be invoked.
        ;;  If we fail to wait, WSACleanup() could be called while an
        ;;  asynchronous query is still in progress, possibly causing a crash.
        ;;
        mov eax,QueryTimeout
        mov ecx,1000
        xor edx,edx
        div ecx
        _tprintf("The query took longer than %d seconds to complete; "
                 "cancelling the query...\n", rax)

        GetAddrInfoExCancel(&CancelHandle)

        WaitForSingleObject(QueryContext.CompleteEvent,
                            INFINITE)
    .endif

done:

    .if (IsWSAStartupCalled)

        WSACleanup()
    .endif

    .if (QueryContext.CompleteEvent)

        CloseHandle(QueryContext.CompleteEvent)
    .endif

    .return Error

_tmain endp

;;
;; Callback function called by Winsock as part of asynchronous query complete
;;

    assume rsi:ptr QUERY_CONTEXT
    assume rdi:ptr ADDRINFOEX

QueryCompleteCallback proc private uses rsi rdi \
    Error: DWORD,
    Bytes: DWORD,
    Overlapped: LPOVERLAPPED

    .new QueryContext:PQUERY_CONTEXT = NULL
    .new QueryResults:PADDRINFOEX = NULL
    .new AddrString[MAX_ADDRESS_STRING_LENGTH]:TCHAR
    .new AddressStringLength:DWORD

    mov QueryContext,CONTAINING_RECORD(Overlapped, QUERY_CONTEXT, QueryOverlapped)
    mov rsi,rax

    .if (Error != ERROR_SUCCESS)

        _tprintf("ResolveName failed with %d\n", Error)
        jmp done
    .endif

    _tprintf("ResolveName succeeded. Query Results:\n")

    mov QueryResults,[rsi].QueryResults
    mov rdi,rax

    .while (QueryResults)

        mov AddressStringLength,MAX_ADDRESS_STRING_LENGTH

        WSAAddressToString([rdi].ai_addr,
                           dword ptr [rdi].ai_addrlen,
                           NULL,
                           &AddrString,
                           &AddressStringLength)

        _tprintf("Ip Address: %s\n", &AddrString)
        mov QueryResults,[rdi].ai_next
        mov rdi,rax
    .endw

done:

    .if ([rsi].QueryResults)

        FreeAddrInfoEx([rsi].QueryResults)
    .endif

    ;;
    ;;  Notify caller that the query completed
    ;;

    SetEvent([rsi].CompleteEvent)
    ret

QueryCompleteCallback endp

    end _tstart

six_L

  • Member
  • **
  • Posts: 218
Re: Asmc source and binaries
« Reply #290 on: April 05, 2021, 09:20:45 AM »
Hi,nidud
How does the "CONTAINING_RECORD" work ?
CONTAINING_RECORD(Overlapped, QUERY_CONTEXT, QueryOverlapped)
Say you, Say me, Say the codes together for ever.

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #291 on: April 05, 2021, 09:43:35 AM »
It's a macro returning an address to a struct.field. Defined in winnt.inc and ntdef.inc

.inline CONTAINING_RECORD fastcall address:ptr, type:abs, field:abs {
   lea rax,[rcx+type.field]
   }

six_L

  • Member
  • **
  • Posts: 218
Re: Asmc source and binaries
« Reply #292 on: April 06, 2021, 01:20:28 PM »
Hi,nidud
thanks your explain.
c++
Code: [Select]
//
// Calculate the address of the base of the structure given its type, and an
// address of a field within the structure.
//

#define CONTAINING_RECORD(address, type, field) ((type *)( \
                                                  (PCHAR)(address) - \
                                                  (ULONG_PTR)(&((type *)0)->field)))
macros
Code: [Select]
CONTAINING_RECORD macro address,type,field
exitm <( ( type * ) ( ( PCHAR ) ( address ) - (  and  ( ( type * ) 0 ) -> field ) ) ) >
endm
;------------------------------------------------------------------------------------------------
ADDRINFOEX struct
   ai_flags   DWORD ?
   ai_family   DWORD ?
   ai_socktype   DWORD ?
   ai_protocol   DWORD ?
   ai_addrlen   QWORD ?
   ai_canonname   LPVOID ?
   ai_addr      LPVOID ?
   ai_blob      LPVOID ?
   ai_bloblen   DWORD ?
   ai_provider   LPVOID ?
   ai_next      LPVOID ?
ADDRINFOEX ENDS
PADDRINFOEX typedef ptr ADDRINFOEX

QUERYCONTEXT struct
   QueryOverlapped   OVERLAPPED <?>
   QueryResults   ADDRINFOEX <?>
   CompleteEvent   HANDLE   ?
QUERYCONTEXT ENDS
PQUERYCONTEXT typedef ptr QUERYCONTEXT
...
mov rcx,CONTAINING_RECORD ( Overlapped, QUERY_CONTEXT, QueryOverlapped )
Quote
Error A2210: Syntax error: QueryOverlapped ) ) ) >
Say you, Say me, Say the codes together for ever.

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #293 on: April 06, 2021, 06:53:07 PM »
Maybe this is wrong. The original macro subtracts the field offset from the address rather than adding it. In this case the field is zero so the macro works but will probably fail otherwise.

six_L

  • Member
  • **
  • Posts: 218
Re: Asmc source and binaries
« Reply #294 on: April 08, 2021, 01:09:46 AM »
Hi,nidud
Would you post the x64 exe about ResolveName.asm (how to use asynchronous GetAddrInfoEx) ?
Say you, Say me, Say the codes together for ever.

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #295 on: April 08, 2021, 02:09:58 AM »
This include EXE and disassembly of the object file.

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #296 on: April 08, 2021, 06:10:49 AM »
Some more HTTP stuff.

Code: [Select]
;;
;; Windows-classic-samples/Samples/HttpInternationalDomainName
;;
;; This sample demonstrates how to use HttpPrepareUrl to get a new URL so that
;; it is safe and valid to use in other HTTPAPIs.
;;
;; IdnSample <inputurl>
;;
;; where:
;;
;; inputurl      The input URL to prepare.
;;

WINVER       equ 0x0603 ; Windows 8.1
_WIN32_WINNT equ 0x0603

include windows.inc
include stdio.inc
include stdlib.inc
include http.inc
include tchar.inc

.code

wmain proc \
    Argc:int_t,
    Argv:ptr PWCHAR

    .new Error:DWORD = ERROR_SUCCESS
    .new PreparedUrl:PWSTR = NULL
    .new Version:HTTPAPI_VERSION = HTTPAPI_VERSION_2
    .new ApiInitialized:BOOL = FALSE

    .repeat

        .if (Argc != 2)

            wprintf(L"Usage: IdnSample <url>\n")
            .break
        .endif

        mov rax,Argv
        mov Argv,[rax+size_t]

        ;;
        ;; Initialize HTTPAPI to use server APIs.
        ;;

        mov Error,HttpInitialize(Version, HTTP_INITIALIZE_SERVER, NULL)

        .break .if (Error != ERROR_SUCCESS)

        mov ApiInitialized,TRUE

        ;;
        ;; Prepare the input url.
        ;;

        mov Error,HttpPrepareUrl(NULL, 0, Argv, &PreparedUrl)

        .break .if (Error != ERROR_SUCCESS)

        wprintf(L"%s prepared is: %s\n", Argv, PreparedUrl)

    .until 1


    .if (PreparedUrl != NULL)

        HeapFree(GetProcessHeap(), 0, PreparedUrl)
        mov PreparedUrl,NULL
    .endif

    .if (ApiInitialized)

        HttpTerminate(HTTP_INITIALIZE_SERVER, NULL)
        mov ApiInitialized,FALSE
    .endif

    .if (Error != ERROR_SUCCESS)

        wprintf(L"Error code = %#lx.\n", Error)
    .endif

    .return Error

wmain endp

    end _tstart

IdnSample http://masm32.com/board/index.php?action=recent
http://masm32.com/board/index.php?action=recent prepared is: http://masm32.com:80/board/index.php

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #297 on: April 08, 2021, 06:21:43 AM »
Asynchronous HTTP Server

This includes a Visual Studio 2019 Debug project.

It's a Console application with a mixture of ASCII and Unicode.

AsyncServer <Url> <ServerDirectory>

Example:
AsyncServer http://masm32.com:80/board/index.php D:\httpsrv

nidud

  • Member
  • *****
  • Posts: 2118
    • https://github.com/nidud/asmc
Re: Asmc source and binaries
« Reply #298 on: April 08, 2021, 06:38:51 AM »
Added DEFINE directive.

DEFINE name [ Value ]

Not very intelligent: it just creates EQU statements.

Code: [Select]
ifndef __COMMON__
define __COMMON__

option wstring:off

ifndef _WIN32_WINNT
;; Specifies that the minimum required platform is Windows Vista.
;; Change this to the appropriate value to target other versions of Windows.
define _WIN32_WINNT 0x0600
endif

.pragma warning(disable:4201)   ;; nameless struct/union
.pragma warning(disable:4214)   ;; bit field types other than int

ifdef __CV__
.pragma comment(linker,"/DEFAULTLIB:libcmtd.lib")
.pragma comment(linker,"/DEFAULTLIB:httpapi.lib")
_LIBCMT equ 1
endif

include stdio.inc
include conio.inc
include stdlib.inc
include http.inc
include strsafe.inc

;;
;; Global defines
;;

;; Use the process heap for all memory allocation.

MALLOC macro x
    exitm<HeapAlloc(GetProcessHeap(), 0, (x))>
    endm
FREE macro x
    exitm<HeapFree(GetProcessHeap(), 0, (x))>
    endm

;; Maximum string size (url, server directory)
define MAX_STR_SIZE 256
;; The number of requests for queueing
define OUTSTANDING_REQUESTS 16
;; The number of requests per processor
define REQUESTS_PER_PROCESSOR 4
;; This is the size of the buffer we provide to store the request.
;; Headers, URL, entity-body, etc will all be stored in this buffer.
define REQUEST_BUFFER_SIZE 4096

CALLBACK(HTTP_COMPLETION_FUNCTION, :ptr _HTTP_IO_CONTEXT, :PTP_IO, :ULONG)

;; Structure for handling http server context data

SERVER_CONTEXT          STRUC
wszRootDirectory        WCHAR MAX_STR_SIZE dup(?)   ;; Server directory
sessionId               HTTP_SERVER_SESSION_ID ?    ;; Session Id
urlGroupId              HTTP_URL_GROUP_ID ?         ;; URL group
hRequestQueue           HANDLE ?                    ;; Request queue handle
Io                      PTP_IO ?                    ;; IO object
bHttpInit               BOOL ?                      ;; TRUE, when the HTTP Server API driver was initialized
bStopServer             BOOL ?                      ;; TRUE, when we receive a user command to stop the server
SERVER_CONTEXT          ENDS
PSERVER_CONTEXT         typedef ptr SERVER_CONTEXT


;; Structure for handling I/O context parameters

HTTP_IO_CONTEXT         STRUC
Overlapped              OVERLAPPED <>               ;; Pointer to the completion function
pfCompletionFunction    HTTP_COMPLETION_FUNCTION ?
pServerContext          PSERVER_CONTEXT ?           ;; Structure associated with the url and server directory
HTTP_IO_CONTEXT         ENDS
PHTTP_IO_CONTEXT        typedef ptr HTTP_IO_CONTEXT

;; Structure for handling I/O context parameters

HTTP_IO_REQUEST         STRUC
ioContext               HTTP_IO_CONTEXT <>
pHttpRequest            PHTTP_REQUEST ?
RequestBuffer           UCHAR REQUEST_BUFFER_SIZE dup(?)
HTTP_IO_REQUEST         ENDS
PHTTP_IO_REQUEST        typedef ptr HTTP_IO_REQUEST

;; Structure for handling I/O context parameters

HTTP_IO_RESPONSE        STRUC
ioContext               HTTP_IO_CONTEXT <>
HttpResponse            HTTP_RESPONSE <>            ;; Structure associated with the specific response
HttpDataChunk           HTTP_DATA_CHUNK <>          ;; Structure represents an individual block of data either in memory,
HTTP_IO_RESPONSE        ENDS                        ;; in a file, or in the HTTP Server API response-fragment cache.
PHTTP_IO_RESPONSE       typedef ptr HTTP_IO_RESPONSE

;;
;; Forward Prototypes
;;

SendCompletionCallback proto \
        pIoContext: PHTTP_IO_CONTEXT,
                Io: PTP_IO,
          IoResult: ULONG

ReceiveCompletionCallback proto \
        pIoContext: PHTTP_IO_CONTEXT,
                Io: PTP_IO,
          IoResult: ULONG


ProcessReceiveAndPostResponse proto \
        pIoRequest: PHTTP_IO_REQUEST,
                Io: PTP_IO,
          IoResult: ULONG


GetFilePathName proto \
          BasePath: PCWSTR,
           AbsPath: PCWSTR,
            Buffer: PWCHAR,
        BufferSize: ULONG


AllocateHttpIoRequest proto \
    pServerContext: PSERVER_CONTEXT


AllocateHttpIoResponse proto \
    pServerContext: PSERVER_CONTEXT


CleanupHttpIoResponse proto \
       pIoResponse: PHTTP_IO_RESPONSE


CleanupHttpIoRequest proto \
        pIoRequest: PHTTP_IO_REQUEST

endif

six_L

  • Member
  • **
  • Posts: 218
Re: Asmc source and binaries
« Reply #299 on: April 08, 2021, 11:57:58 AM »
Hi,nidud
the ResolveName.exe works fine.
Thanks you for many useful examples. :thumbsup:   
Say you, Say me, Say the codes together for ever.