The MASM Forum

General => The Workshop => Topic started by: Vortex on December 23, 2012, 11:25:27 PM

Title: GNU Assembler example
Post by: Vortex on December 23, 2012, 11:25:27 PM
Here is a GNU Assembler example. It's created with as.exe and ld.exe coming with MinGW - Minimalist GNU for Windows.

Thanks to baldr for his GAS invoke macro.

Code: [Select]
.intel_syntax noprefix
.global _start

.include "invoke.inc"
.include "Dlgbox.inc"

.data

DlgName:
.asciz "MyDialog"

.bss

hInstance:
    .long 0

hCursor:
    .long 0

.text

_start:

    invoke  GetModuleHandle,0
    mov     hInstance,eax
   
    invoke  DialogBoxParam,hInstance,"OFFSET DlgName",0,"OFFSET DlgProc",0
           
    invoke  ExitProcess,eax


// DlgProc PROC hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

DlgProc:

    push    ebp
    mov     ebp,esp

    cmp     dword ptr [ebp+uMsg], WM_CLOSE
            jne     initdlg
            invoke  EndDialog,[ebp+hWnd],0
            jmp     true

initdlg:

    cmp     dword ptr [ebp+uMsg], WM_INITDIALOG
            jne     setcursor
            invoke  LoadCursor,0,IDC_CROSS
            mov     hCursor,eax
            jmp     true

setcursor:

    cmp     dword ptr [ebp+uMsg], WM_SETCURSOR

jne       false
invoke    SetCursor,hCursor
jmp       true

false:

    xor     eax,eax
    pop     ebp
    ret     4*4

true:

    mov     eax,1
    pop     ebp
    ret     4*4

// DlgProc ENDP

// END start

Building the project :

Code: [Select]
set PATH=%PATH%;E:\MinGW\bin;E:\MinGW\msys\1.0\bin

windres Rsrc.rc Rsrc.o
as -o Dlgbox.o Dlgbox.asm
ld -e _start -subsystem windows -o Dlgbox.exe Dlgbox.o Rsrc.o -lkernel32 -luser32 -s

EDIT : Removed the unnecessary parameter  -LE:\MinGW\lib from ld.exe
Title: Re: GNU Assembler example
Post by: Gunther on December 23, 2012, 11:46:11 PM
hi Vortex,

solid work.  :t

The source code is similar to the masm source code. It seems that gas performs well.

Gunther
Title: Re: GNU Assembler example
Post by: Vortex on December 23, 2012, 11:57:13 PM
Hi Gunther,

Masm is better as it's macro engine is much more poweful.
Title: Re: GNU Assembler example
Post by: Gunther on December 24, 2012, 12:05:54 AM
Hi Vortex,

Masm is better as it's macro engine is much more poweful.

no doubts about that. But it's interesting that we've now an invoke macro for gas.

Gunther
Title: Re: GNU Assembler example
Post by: Vortex on December 24, 2012, 01:50:28 AM
Hi Gunther,

The author of the macro is a member of the Asm community forum. Another member of the forum, theorizer wrote the macro below :

Code: [Select]
.altmacro       
.macro ccall func:req, arg1, args:vararg
        local argc
        argc = 0

        /* recursive reverse pusher */
        .macro pusher parg1, pargs:vararg
                .ifnb \parg1
                        pusher  \pargs
                        push    \parg1
                        argc = argc + 1
                .endif
        .endm

        pusher  \arg1 \args
        call    \func
        /* check if there were arguments pushed */
        .if \argc
                add     esp, argc * 4
        .endif
.endm
Title: Re: GNU Assembler example
Post by: Vortex on December 24, 2012, 02:15:25 AM
Attached is an example of Masm object file linking with GNU linker ld.exe

Code: [Select]
set PATH=%PATH%;E:\MinGW\bin;E:\MinGW\msys\1.0\bin

\masm32\bin\ml /c /coff *.asm

ld -e _WinMainCRTStartup -subsystem windows -o SimpleWnd.exe SimpleWnd.obj crt0gui.obj -lkernel32 -luser32 -s
Title: Re: GNU Assembler example
Post by: Gunther on December 24, 2012, 02:42:52 AM
Hi Vortex,

The author of the macro is a member of the Asm community forum. Another member of the forum, theorizer wrote the macro below :

why not. There are of course qualified assembly language programmers in that forum.

Gunther
Title: Re: GNU Assembler example
Post by: MichaelW on December 24, 2012, 09:15:22 AM
I posted a pair of macros somewhere in the 2008-2009 range. They are not as compact as these later ones, and may assemble somewhat slower. AFAIK this is the original code, but with expanded comments.
Code: [Select]
//.intel_syntax noprefix
//.altmacro

/*
; For irp the statements are assembled at least once, so in
; the ifnc blocks that count the arguments detecting a
; no-args condition requires a check for a null argument.
;
; The clumsy double-loop arrangement is the only compact and
; flexible method that I could find to push the arguments in
; right to left order.
;
; These macros are coded to minimize the number of loops (an
; exitm directive in a loop exits the innermost loop only).
;
; These macros work correctly with no optional arguments.
;
; The cinvoke macro assumes 32-bit arguments. Byte or word
; arguments can be passed by zero or sign extending them
; into a 32-bit register and passing the register. Qword
; arguments can be passed as two dword arguments, with the
; low-order dword on the left and the high-order dword on
; the right, as they appear in the cinvoke statement.
;
; Because the cinvoke macro calls the invoke macro, certain
; types of errors in the cinvoke macro arguments will cause
; errors to be reported for both macros.
*/

.macro invoke, func:req, args:vararg
    n=0
    .irp arg,\args
      .ifnc \arg,
        n=n+1
      .endif
    .endr
    .if n>0
      i=n
      .irp junk,\args
        j=0
        .irp arg,\args
          j=j+1
          .if j==i
            push arg
            .exitm
          .endif
        .endr
        i=i-1
      .endr
    .endif
    call \func
.endm

.macro cinvoke, func:req, args:vararg
    n=0
    .irp arg,\args
      .ifnc \arg,
        n=n+1
      .endif
    .endr
    invoke \func, \args
    .if n>0
      add esp, n*4
    .endif
.endm

IIRC I was able to use these macros in FreeBASIC inline assembly.

Also, the minimum workable version of as for these macros is somewhere between 2.15.94 and 2.18.50.
Title: Re: GNU Assembler example
Post by: Vortex on December 25, 2012, 06:09:16 AM
Hi MichaelW,

Thanks for the macro.

Trying your version of invoke on the example I posted above, I got the error messages below :

Code: [Select]
Dlgbox.o:fake:(.text+0x2): undefined reference to `arg'
Dlgbox.o:fake:(.text+0x12): undefined reference to `arg'
Dlgbox.o:fake:(.text+0x18): undefined reference to `arg'
Dlgbox.o:fake:(.text+0x1e): undefined reference to `arg'
Dlgbox.o:fake:(.text+0x24): undefined reference to `arg'
Dlgbox.o:fake:(.text+0x2a): more undefined references to `arg' follow

I added a slash \ symbol to the push statement and this solved the problem :

Modifying from :

Code: [Select]
.if j==i
            push arg
            .exitm
          .endif

to :

Code: [Select]
.if j==i
            push \arg
            .exitm
          .endif

Tools : binutils-2.23.1 dating 15 November 2012

MichaelW, I tried to split the long line below but it didn't work for me :

Code: [Select]
invoke  DialogBoxParam,hInstance,"OFFSET DlgName",0,"OFFSET DlgProc",0
Code: [Select]
invoke  DialogBoxParam,\
            hInstance,\
            "OFFSET DlgName",\
            0,"OFFSET DlgProc",0

Code: [Select]
Dlgbox.asm: Assembler messages:
Dlgbox.asm:27: Warning: stray `\'
Dlgbox.asm:27: Warning: stray `\'
Dlgbox.asm:27: Warning: stray `\'
Dlgbox.asm:27: Warning: stray `\'
Dlgbox.asm:27: Warning: stray `\'
Dlgbox.asm:27: Warning: stray `\'
Dlgbox.asm:27: Error: invalid character '\' before operand 1
Dlgbox.asm:28: Warning: stray `\'
Dlgbox.asm:28: Error: invalid character ',' in mnemonic
Dlgbox.asm:29: Error: junk at end of line, first unrecognized character is `"'
Dlgbox.asm:30: Error: junk at end of line, first unrecognized character is `0'

How can I break the line into multiple lines in GAS?
Title: Re: GNU Assembler example
Post by: MichaelW on December 25, 2012, 05:34:51 PM
Hi Vortex,

My macros require the  .altmacro directive (http://sourceware.org/binutils/docs-2.23.1/as/Altmacro.html#Altmacro). Sorry, I should have stated this. I commented it out in the macro source because I normally include it in the assembly source.

For the line continuation problem I found this:
http://linuxvm.org/present/SHARE99/S8131db.pdf
Quote
GAS is free-form. Continuation is indicated by ending a line with a backslash (\), just like C.
But it does not seem to work with my macros.

Title: Re: GNU Assembler example
Post by: Vortex on December 26, 2012, 05:46:47 AM
Hi MichaelW,

Many thanks for the information and the link. Your macro works fine without the .altmacro statement. The backslash symbol didn't work for me too.
Title: Re: GNU Assembler example
Post by: Vortex on December 29, 2012, 09:00:09 PM
Some links :

Installing MinGW on Windows (http://kemovitra.blogspot.com/2012/11/installing-mingw-on-windows.html)

How to install MinGW, MSYS and Eclipse on windows (http://www.multigesture.net/articles/how-to-install-mingw-msys-and-eclipse-on-windows)
Title: Re: GNU Assembler example
Post by: Vortex on December 29, 2012, 09:15:46 PM
IDE for MinGW : Code::Blocks Portable

http://portableapps.com/node/18671

Title: Re: GNU Assembler example
Post by: Vortex on December 31, 2012, 09:07:39 PM
For those who would like to use latest versions of as.exe and ld.exe from the Cygwin package, the dependencies are the following :

Code: [Select]
cygwin1.dll
cygiconv-2.dll
cygintl-8.dll
Title: Re: GNU Assembler example
Post by: Gunther on January 02, 2013, 04:45:10 AM
Hi Vortex,

Some links :

Installing MinGW on Windows (http://kemovitra.blogspot.com/2012/11/installing-mingw-on-windows.html)

MinGW is a solid tool. I'm working with it since many years and it has the same behaviour like the original gcc.

Gunther
Title: Re: GNU Assembler example
Post by: Vortex on January 02, 2013, 05:50:56 AM
Same example linked with Polink.exe :

Code: [Select]
\masm32\bin\polink /SUBSYSTEM:WINDOWS /ENTRY:start /LIBPATH:\masm32\lib Dlgbox.o Rsrc.o kernel32.lib user32.lib
Title: Re: GNU Assembler example
Post by: Vortex on November 18, 2020, 03:51:42 AM
GUI example coded by MichaelW :

https://www.freebasic.net/forum/viewtopic.php?f=6&t=10432&start=15

Attached is project built with GNU Binutils 2.28