Author Topic: GNU Assembler example  (Read 19952 times)

Vortex

  • Member
  • *****
  • Posts: 2457
GNU Assembler example
« 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

Gunther

  • Member
  • *****
  • Posts: 3585
  • Forgive your enemies, but never forget their names
Re: GNU Assembler example
« Reply #1 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
Get your facts first, and then you can distort them.

Vortex

  • Member
  • *****
  • Posts: 2457
Re: GNU Assembler example
« Reply #2 on: December 23, 2012, 11:57:13 PM »
Hi Gunther,

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

Gunther

  • Member
  • *****
  • Posts: 3585
  • Forgive your enemies, but never forget their names
Re: GNU Assembler example
« Reply #3 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
Get your facts first, and then you can distort them.

Vortex

  • Member
  • *****
  • Posts: 2457
Re: GNU Assembler example
« Reply #4 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

Vortex

  • Member
  • *****
  • Posts: 2457
Re: GNU Assembler example
« Reply #5 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

Gunther

  • Member
  • *****
  • Posts: 3585
  • Forgive your enemies, but never forget their names
Re: GNU Assembler example
« Reply #6 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
Get your facts first, and then you can distort them.

MichaelW

  • Global Moderator
  • Member
  • *****
  • Posts: 1209
Re: GNU Assembler example
« Reply #7 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.
Well Microsoft, here’s another nice mess you’ve gotten us into.

Vortex

  • Member
  • *****
  • Posts: 2457
Re: GNU Assembler example
« Reply #8 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?

MichaelW

  • Global Moderator
  • Member
  • *****
  • Posts: 1209
Re: GNU Assembler example
« Reply #9 on: December 25, 2012, 05:34:51 PM »
Hi Vortex,

My macros require the .altmacro directive. 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.

Well Microsoft, here’s another nice mess you’ve gotten us into.

Vortex

  • Member
  • *****
  • Posts: 2457
Re: GNU Assembler example
« Reply #10 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.

Vortex

  • Member
  • *****
  • Posts: 2457

Vortex

  • Member
  • *****
  • Posts: 2457
Re: GNU Assembler example
« Reply #12 on: December 29, 2012, 09:15:46 PM »
IDE for MinGW : Code::Blocks Portable

http://portableapps.com/node/18671


Vortex

  • Member
  • *****
  • Posts: 2457
Re: GNU Assembler example
« Reply #13 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

Gunther

  • Member
  • *****
  • Posts: 3585
  • Forgive your enemies, but never forget their names
Re: GNU Assembler example
« Reply #14 on: January 02, 2013, 04:45:10 AM »
Hi Vortex,

Some links :

Installing MinGW on Windows

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

Gunther
Get your facts first, and then you can distort them.