News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

A very simple GAS example

Started by Vortex, December 18, 2005, 04:15:53 PM

Previous topic - Next topic

hutch--

I have a working complete set of macros that make the API functions more or less high level function in the following form. I just did not know if anyone was interested in them. I have also ripped a set of equates from the masm32 windows.inc that seem to be working OK. All I am having trouble with at the moment is a convenient way to handle structures. If anyone is interested I will post a set somewhere so they are available.

.extern _ActivateKeyboardLayout@8
.macro ActivateKeyboardLayout arg1 arg2
push \arg2
push \arg1
call _ActivateKeyboardLayout@8
.endm

.extern _AdjustWindowRect@12
.macro AdjustWindowRect arg1 arg2 arg3
push \arg3
push \arg2
push \arg1
call _AdjustWindowRect@12
.endm

.extern _AdjustWindowRectEx@16
.macro AdjustWindowRectEx arg1 arg2 arg3 arg4
push \arg4
push \arg3
push \arg2
push \arg1
call _AdjustWindowRectEx@16
.endm
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

Hutch,

I'm interested. GAS is a pretty darn good assembler. I had always avoided it before, mainly because of the AT&T syntax. Now that it supports Intel syntax, I like it. Another tool for the toolkit.



GregL

Is there a way to handle varargs in the macros?


MichaelW

FWIW I spent several hours today trying to create an invoke macro. I could find no good, clean method of using a variable number of arguments. Any macro call with more arguments than parameters would trigger "Error: too many positional arguments". When I switched to more parameters than arguments, I could find no direct method of determining which parameters were blank. What I am doing for now is passing the number of arguments and using that to determine which of the other arguments to process. Another problem was that an argument of the form "offset arg" would expand to two arguments. I was able to fix this by specifying the arguments as offset(arg).

    .macro invoke func,argcnt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10
      .if \argcnt > 9
        push \a10
      .endif
      .if \argcnt > 8
        push \a9
      .endif 
      .if \argcnt > 7
        push \a8
      .endif
      .if \argcnt > 6
        push \a7
      .endif
      .if \argcnt > 5
        push \a6
      .endif
      .if \argcnt > 4
        push \a5
      .endif
      .if \argcnt > 3
        push \a4
      .endif
      .if \argcnt > 2
        push \a3
      .endif       
      .if \argcnt > 1
        push \a2
      .endif
      .if \argcnt > 0
        push \a1
      .endif
      call \func
    .endm

invoke MessageBox,4,0,offset(message),offset(buffer),MB_OK | MB_ICONASTERISK



I think a better method would be to append the number of arguments to the function name, perhaps just the way it is in the include files, for example _MessageBoxA@16, but I don't see where GAS provides any method of extracting the number from the name.


eschew obfuscation

hutch--

Sorry to be a bit slow but I have been doing a lot of checking and experimenting with the include file layout. The currect batch are macros in the form suggested above that work as a form of type checking as you at least get some response if the argument count is incorrect. You can either use the macro which is just automated push/call or you can directly use CALL on the undecorated name.

You can do a passable emulation of a structure in the .data section with the following.


  .align 8
  // WNDCLASSEX structure
    wc_cbSize:          .long 48
    wc_style:           .long CS_BYTEALIGNWINDOW | CS_BYTEALIGNCLIENT
    wc_lpfnWndProc:     .long WndProc
    wc_cbClsExtra:      .long 0
    wc_cbWndExtra:      .long 0
    wc_hInstance:       .long 0
    wc_hIcon:           .long 0
    wc_hCursor:         .long 0
    wc_hbrBackground:   .long 0
    wc_lpszMenuName:    .long 0
    wc_lpszClassName:   .long szclassname
    wc_hIconSm:         .long 0


Michael solved the problem of using OFFSET with the macros with the brackets.

There is a big file winequ.gi (gas include) that has a lot of equates in it but the file is rough in that it does not properly handle joined styles. I fixed the WS_OVERLAPPEDWINDOW one for one of the examples but the file needs to be done a lot better than it currently is.

One example is a resource less window that seems to work OK. I have included the two batch files I have been using to build examples and I have so far continued to use the masm32 API import libraries. The MASM32 library is also used.

http://www.masmforum.com/private/gas.zip
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

MichaelW

Thanks Hutch :U

A bit slow? You either have very sore fingers now, or you somehow automated the creation of all this.

eschew obfuscation

Bieb

Say, would anyone happen to know how to write a simple command line program under Linux using GAS?

Vortex

Hi Hutch,

Very nice work :U
I guess you have a special tool to convert the master windows.inc file to GAS syntax.

GregL

MichaelW,

I came up with something almost identical to what you did for variable arguments. I was hoping there was a better way.

offset(arg)  :U


Hutch,

Thanks.




Vortex

MichaelW, thanks for your invoke macro  :U

Based on the macro, I added a feature to support GAS to my tool external function scanner :
// Original example by Hutch

    .intel_syntax noprefix
    .global _start

    .macro szByteCopy arg1,arg2
      push \arg2
      push \arg1
      call szcopy
    .endm

    .macro m2m arg1,arg2
      push \arg2
      pop  \arg1
    .endm

    .include "invoke.gi"
    .include "msgbox.imp"

    .set MB_ICONASTERISK, 0x40
    .set MB_OK, 0x0

  // -----------------------
  // zero terminated strings
  // -----------------------

  .data
    message: .ascii "Its a GAS Its a GAS Its a GAS Its a GAS\n"
             .ascii "Its a GAS Its a GAS Its a GAS Its a GAS\n"
             .ascii "Its a GAS Its a GAS Its a GAS Its a GAS\x00"

    caption: .ascii "Hey man !\x00"

// -----------------------------------
// pointers to zero terminated strings
// -----------------------------------
    pmsg: .long message
    pttl: .long caption

.text

/* ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««« */

_start:

    .bss
      buffer: .fill 128         /*  128 byte buffer  */
    .data
      pbuf:   .long buffer      /* pointer to buffer */
    .text

    invoke GetCL,2,1,pbuf
    cmp eax, 1
    jne nocl

    invoke MessageBox,4,0,pbuf,pttl,MB_OK | MB_ICONASTERISK

    jmp quit

  nocl:
    .data
      nomsg: .ascii "No command line argument was entered\x00"
      nottl: .ascii "Sorry ....\x00"
      pnm: .long nomsg
      pnt: .long nottl
    .text
    invoke MessageBox,4,0,pnm,pnt,MB_OK | MB_ICONASTERISK

  quit:
    invoke ExitProcess,1,0

/* ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««« */

  .align 8
  szcopy:

    mov ecx, [esp+4]
    mov edx, [esp+8]

    push ebx
    xor ebx, ebx

  cpy:
  .rept 3
    mov al, [ecx+ebx]
    mov [edx+ebx], al
    add ebx, 0x01
    test al, al
    jz cpout
  .endr

    mov al, [ecx+ebx]
    mov [edx+ebx], al
    add ebx, 0x01
    test al, al
    jnz cpy

  cpout:

    pop ebx

    ret 8

/* ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««« */


Building the demo :

scan Msgbox.as -ga
as -o Msgbox.obj Msgbox.as
ld -e_start -subsystem windows -L\masm32\lib -o Msgbox.exe Msgbox.obj --library=masm32 --library=user32 --library=kernel32 -s


The output of scan for external functions :

.extern _ExitProcess@4
.set ExitProcess,_ExitProcess@4

.extern _MessageBoxA@16
.set MessageBox,_MessageBoxA@16

.extern _GetCL@8
.set GetCL,_GetCL@8

[attachment deleted by admin]

hutch--

I have just finished a much better equate file for AS. This one properly handles the joined ORRED styles.

So far I have not found a way to pass quoted strings to a macro, anyone know if it can be done ?

[attachment deleted by admin]
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

NPNW

Hutch,

So far I have not found a way to pass quoted strings to a macro, anyone know if it can be done ?

.ascii "Its a GAS Its a GAS Its a GAS Its a GAS\x00"

You mean something like this?

.ascii ""its a GAS" "Its a GAS" "Its a GAS "Its a GAS"\x00"

Wouldn't this be a problem with the .ascii directive in the GAS compiler?
You would have to make your own routine to keep the " " symbols.

Your table parser rountine useing ascii characters would probably be able to handle this type of conversion as a template. Then you could simplify with a small set symbols or single symbol if you just wanted it to handle the "". Otherwise, I don't know of routines although my knowledge is limited.
Hope this helps give ideas.







hutch--

I found ".altmacro" buried in the documentation,


    .altmacro
    .macro sztext uname,quoted_text
      .data
        uname&: .string quoted_text
      .text
    .endm
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

James Ladd

Ok, here is my super simple GAS example as it doesnt have any code really, just calls exit.
There is a make to simplify assembling and linking.
I'll extend the example to include a DLL and call a function in it.

Does anyone know where I can find the 'invoke' macro used in the other examples
below that works with GAS?

Note: Im using cygwin under WinXP to build my examples.

Rgs, James.

simple.s

.intel_syntax noprefix

.arch pentium

.global _start

.data
    .extern _ExitProcess@4

.text

_start:

    xor eax, eax
    pushd 0
    call _ExitProcess@4


Makefile  (note that there are tabs in the Makefile)


SRC = simple.s

OBJ = simple.o

BIN = simple

LIBS = kernel32


all: $(OBJ) $(BIN)

clean:
rm -f $(OBJ)
rm -f $(BIN)

.s.o:
as -g -o $@ $<

simple: simple.o
ld -e_start -o simple simple.o -l$(LIBS)


Vortex

Here is a dialog box example with GAS :

.intel_syntax noprefix
.global _start

.include "invoke.gi"
.include "Dlgbox.gi"

.data
DlgName:
    .asciz "MyDialog"

.bss
hInstance:
    .long 0
hCursor:
    .long 0

.text

_start:

invoke     GetModuleHandle,1,0
mov        hInstance,eax
invoke     DialogBoxParam,5,hInstance,OFFSET(DlgName),0,OFFSET(DlgProc),0
invoke     ExitProcess,1,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,2,[ebp+hWnd],0
            jmp     true

initdlg:

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

setcursor:

    cmp     dword ptr [ebp+uMsg], WM_SETCURSOR

jne       false
invoke    SetCursor,1,hCursor
jmp       true

false:

    xor     eax,eax
    pop     ebp
    ret     16

true:

    mov     eax,1
    pop     ebp
    ret     16

[attachment deleted by admin]