simple console, gui app or dll with pure as.exe and ld.exe ?

Windows specific questions.
D.J.Peters
Posts: 8208
Joined: May 28, 2005 3:28
Contact:

Postby D.J.Peters » Jan 21, 2008 15:58

srvaldez@
ESP points to the number of args if it is a ELF Linux app

Joshy
fsw
Posts: 260
Joined: May 27, 2005 6:02

Postby fsw » Jan 21, 2008 16:04

D.J.Peters wrote:Hello Michael .altmacro was the key to use string literals as macro params.

thank you

Joshy

Code: Select all

.intel_syntax noprefix
.altmacro

.macro Const c
  push \c
.endm

.macro ByVal v
  mov  eax, offset \v
  mov  eax,[eax]
  push eax
.endm

.macro ByRef r
  push offset \r
.endm

.macro Dim var, typ=.Long, val=0
  .data
    \var: \typ  \val
    .if typ==.ascii
      Len\var: .Long .-\var
    .endif
  .text
.endm

.macro GetStdOut Handle
   Const -11
   call  _GetStdHandle@4
   mov   edi,offset \Handle
   mov   [edi],eax
.endm

.macro Init
  .globl _mainCRTStartup
  Dim tmp
  .text
  .balign 16
_mainCRTStartup:
  push   ebp
  mov    ebp,esp
  call  _AllocConsole@0
.endm

.macro Exit ErrCode=0
  call   _FreeConsole@0
  Const  \ErrCode
  call   _ExitProcess@4
  leave
  ret
.endm

.macro StdOut Handle,Text,Size=-1
  Const 0
  ByRef tmp
  .if \Size==-1
    Const Len\Text
  .else
    Const \Size
  .endif
  ByRef \Text
  ByVal \Handle
  call _WriteConsoleA@20
.endm


#
# main
#
 
  Dim hOut
  Dim Msg1,.ascii,<Hello World 1\n\r>
  Dim Msg2,.ascii,"Hello World 2\n\r"
  Init
  GetStdOut hOut
  StdOut    hOut, Msg1
  StdOut    hOut, Msg2
  Exit


Is this code supposed to work out of the box?
This is what I get:

asm_BASIC.asm: Assembler messages:
asm_BASIC.asm:71: Error: non-constant expression in ".if" statement
asm_BASIC.asm:72: Error: non-constant expression in ".if" statement
asm_BASIC.asm:73: Error: non-constant expression in ".if" statement
asm_BASIC.asm:74: Error: non-constant expression in ".if" statement

!!! ASSEMBLER Error !!!
Press any key to continue . . .
D.J.Peters
Posts: 8208
Joined: May 28, 2005 3:28
Contact:

Postby D.J.Peters » Jan 21, 2008 16:14

hello fsw
i use as.exe ld.exe ar.exe and gdb.exe from MinGW package
not from \freebasic\bin\win32 folder

Joshy

Code: Select all

D:\FBEXAM~1\compi\tests>as -version
GNU assembler 2.16.91 20060119
Copyright 2005 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License.  This program has absolutely no warranty.
This assembler was configured for a target of `mingw32'.

D:\FBEXAM~1\compi\tests>build test

assemble test.asm to test.o

link test.o to test.exe

test.exe created

press a key to run test.exe

Hello World 1
Hello World 2

return code from test.exe are 0
fsw
Posts: 260
Joined: May 27, 2005 6:02

Postby fsw » Jan 21, 2008 17:49

D.J.Peters wrote:hello fsw
i use as.exe ld.exe ar.exe and gdb.exe from MinGW package
not from \freebasic\bin\win32 folder

Joshy

Code: Select all

D:\FBEXAM~1\compi\tests>as -version
GNU assembler 2.16.91 20060119
Copyright 2005 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License.  This program has absolutely no warranty.
This assembler was configured for a target of `mingw32'.

D:\FBEXAM~1\compi\tests>build test

assemble test.asm to test.o

link test.o to test.exe

test.exe created

press a key to run test.exe

Hello World 1
Hello World 2

return code from test.exe are 0


Thanks, using a different version of as seems to make a difference.
The as version from MinGW I have is younger than yours:
GNU assembler 2.17.50 20060824

and the error message is now:
asm_BASIC.asm: Assembler messages:
asm_BASIC.asm:72: Error: junk at end of line, first unrecognized character is `H'

!!! ASSEMBLER Error !!!
D.J.Peters
Posts: 8208
Joined: May 28, 2005 3:28
Contact:

Postby D.J.Peters » Jan 21, 2008 19:24

hello fsw can you try this please

Joshy

Code: Select all

.intel_syntax noprefix
.altmacro

.macro Const c
  push \c
.endm

.macro ByVal v
  push [\v]
.endm

.macro ByRef r
  push offset \r
.endm

.macro Dim var, typ=.Long, val=0
  .data
    \var: \typ  \val
    .if typ==.ascii
      Len\var: .Long .-\var
    .endif
  .text
.endm

.macro GetCommandLine
  call _GetCommandLineA@0
.endm

.macro GetStdHandle chn,Handle
  Const chn
  call _GetStdHandle@4
  mov   [\Handle],eax
.endm

.macro Init
.globl _mainCRTStartup
  .text
  .balign 16
_mainCRTStartup:
  push   ebp
  mov    ebp,esp
  call _AllocConsole@0
.endm

.macro ExitProcess ErrCode=0
  Const \ErrCode
  call _ExitProcess@4
.endm

.macro Exit ErrCode=0
  call _FreeConsole@0
  ExitProcess \ErrCode
  leave
  ret
.endm

.macro WriteConsole Handle,Text,Size,Written
  Const 0
  ByRef \Written
  Const \Size
  ByRef \Text
  ByVal \Handle
  call _WriteConsoleA@20
.endm


#
# main
#
Dim hOut
Dim Written
Dim Msg1,.ascii,"Hello World 1\n\r"
Dim CmdLine,.ascii,"commandline=                                     \n\r"

Init
GetCommandLine
mov esi,eax
mov edi,offset CmdLine
add edi,12
0: mov al,[esi]
   or al,al
   jz 1f
   mov [edi],al
   inc esi
   inc edi
   jmp 0b
1:
GetStdHandle -11,hOut
WriteConsole hOut,Msg1   ,LenMsg1   ,Written
WriteConsole hOut,CmdLine,LenCmdLine,Written
Exit
as test01.asm -o test01.o
ld -s -o test01.exe test01.o -l kernel32
test01 commandline test !!!
Hello World 1
commandline=test01 commandline test !!!
fsw
Posts: 260
Joined: May 27, 2005 6:02

Postby fsw » Jan 21, 2008 20:08

Thanks, 'as' works now as expected.
The object file is 1013 bytes.
No error messages.

If only the stupid 'ld' would find the kernel32 lib.
I've even copied the lib into the same directory...

fsw
D.J.Peters
Posts: 8208
Joined: May 28, 2005 3:28
Contact:

Postby D.J.Peters » Jan 21, 2008 21:57

fsw wrote:The object file is 1013 bytes.

and the exe are only 2048 bytes (with the strings included)

i can't find out how to handle a struc/type in GAS?

Joshy
fsw
Posts: 260
Joined: May 27, 2005 6:02

Postby fsw » Jan 21, 2008 22:10

fsw wrote:If only the stupid 'ld' would find the kernel32 lib.
I've even copied the lib into the same directory...


ld is so dumb it doesn't even look into his own directory it needs the -L option with the proper directory name :P
fsw
Posts: 260
Joined: May 27, 2005 6:02

Postby fsw » Jan 21, 2008 22:22

D.J.Peters wrote:
fsw wrote:The object file is 1013 bytes.

and the exe are only 2048 bytes (with the strings included)
Joshy


Here it's 2093 bytes which seems odd.

Also ld gives the following message:
ld: warning: cannot find entry symbol _mainCRTStartup; defaulting to 00401000

but _mainCRTStartup is there (in a macro).

And finally: it crashes.
fsw
srvaldez
Posts: 2635
Joined: Sep 25, 2005 21:54

Postby srvaldez » Jan 21, 2008 23:06

D.J.Peters, your last example works, no errors or crashes. :)
D.J.Peters
Posts: 8208
Joined: May 28, 2005 3:28
Contact:

Postby D.J.Peters » Jan 21, 2008 23:38

srvaldez wrote:... no errors or crashes.
:-)
fsw wrote:...And finally: it crashes.
:-(
fsw can you post the output from "ld -version" ?

Joshy

by the way struct\type in GAS syntax

Code: Select all

VECTOR3D:
  .struct 0
x:
  .struct x + 4
y:
  .struct y + 4
z:
  .struct z + 4
SIZE_VECTOR3D:
fsw
Posts: 260
Joined: May 27, 2005 6:02

Postby fsw » Jan 22, 2008 0:57

D.J.Peters wrote:fsw can you post the output from "ld -version" ?


Using the same object file:

GNU ld version 2.15.94 20050118
test.exe file size 2093 bytes

GNU ld version 2.17.50 20060824
test.exe file size 1536 bytes

both times it crashes...


Which ld version du you have?

bye
fsw
D.J.Peters
Posts: 8208
Joined: May 28, 2005 3:28
Contact:

Postby D.J.Peters » Jan 22, 2008 1:18

GNU assembler 2.16.91 20060119
GNU ld version 2.16.91 20060119

will this crash too?

Joshy

test.asm

Code: Select all

.intel_syntax noprefix
.macro Const c
  push \c
.endm

.macro Byval v
  mov  eax, offset \v
  mov  eax,[eax]
  push eax
.endm

.macro Byref r
  push offset \r
.endm

.macro GetStdOut Handle
   push -11
   Call  _GetStdHandle@4
   mov   [\Handle],eax
.endm

.macro Init
  .globl _mainCRTStartup
  .text
  .balign 16
_mainCRTStartup:
  push   ebp
  mov    ebp,esp
  Call  _AllocConsole@0
.endm

.macro Exit ErrCode=0
  Call   _FreeConsole@0
  Const  \ErrCode
  Call   _ExitProcess@4
  leave
  ret
.endm

.macro WriteConsole Handle,Text,Size,Written
  Const 0
  Byref \Written
  Const \Size
  Byref \Text
  Byval \Handle
  Call _WriteConsoleA@20
.endm


#
# main
#
  Init
  GetStdOut    hOut
  WriteConsole hOut, Msg1,LenMsg1,Written
  WriteConsole hOut, Msg2,LenMsg1,Written
  Exit

.data
  hOut:    .long 0
  Written: .long 0
  Msg1:    .ascii "Hello World 1\n\r"
  LenMsg1: .long .-Msg1
  Msg2:    .ascii "Hello World 2\n\r"
  LenMsg2: .long .-Msg2

Code: Select all

D:\FBEXAM~1\compi\tests>dir .\lib
17.01.2006  20:12           655.198 libkernel32.a

D:\FBEXAM~1\compi\tests>as test.asm -o test.o
D:\FBEXAM~1\compi\tests>ld -s -L lib test.o -o test.exe -l kernel32
D:\FBEXAM~1\compi\tests>test
Hello World 1
Hello World 2
fsw
Posts: 260
Joined: May 27, 2005 6:02

Postby fsw » Jan 22, 2008 15:54

This time the object file size is 858 bytes and the exe size is 2048 bytes.

The best thing is: it works fine.

Great job!
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Postby MichaelW » Feb 17, 2008 3:47

This is a simple Windows GUI app done completely in assembly. I used the as and ld from Binutils 2.18.50, available here, and the import libraries from a fairly recent distribution of MinGW. I did not determine if the version of AS included with FB will work for this. I assembled and linked from SciTE using these commands (EDIT: Corrected a really stupid error in the -Lsearchdir option):

Code: Select all

command.name.0.*.asm=Assemble
command.0.*.asm=as -v -alsm="$(FileName).lst" -o "$(FileName).o" $(FileNameExt)

command.name.1.*.asm=LinkCon
command.1.*.asm=ld "$(FileName).o" -e start -subsystem console -L"C:\MinGW\lib" -l kernel32 -l user32 -l gdi32 -l msvcrt -o "$(FileName).exe"

command.name.2.*.asm=LinkGui
command.2.*.asm=ld "$(FileName).o" -e start -subsystem windows -L"C:\MinGW\lib" -l kernel32 -l user32 -l gdi32 -l msvcrt -o "$(FileName).exe"

In case anyone is not familiar with this, invoke is a statement, supported by MASM and several other x86 assemblers, that automates the process of calling procedures that take arguments. The alternative of pushing the arguments in reverse order before calling the procedure, and for procedures that use the C calling convention balancing the stack after the call returns, is error prone and requires significantly more effort.

macros.asm:

Code: Select all

.intel_syntax noprefix
.altmacro

// For irp the statements are assembled at least once, so
// detecting a no-args condition requires a check for a
// null argument.
//
// The clumsy double-loop arrangement is the only reasonably
// compact method that I could find to push the arguments in
// reverse order.
//
// These macros are coded to minimize the number of loops.
// An .exitm directive in a loop exits the loop only.
//
// These macros work correctly with no optional arguments.
//
// 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

guitest.inc:

Code: Select all

.intel_syntax noprefix
.altmacro

BLACK_BRUSH = 4

CS_BYTEALIGNWINDOW = 0x2000

IDI_APPLICATION = 32512
IDC_ARROW = 32512

PM_REMOVE = 1

SM_CXSCREEN = 0
SM_CYSCREEN = 1

SW_SHOWNORMAL = 1

WS_EX_OVERLAPPEDWINDOW = 0x300

WM_CLOSE   = 0x10
WM_DESTROY = 0x2
WM_PAINT   = 0xf
WM_QUIT    = 0x12
WM_COMMAND = 0x111
WM_TIMER   = 0x113

WS_OVERLAPPED       = 0
WS_MAXIMIZEBOX      = 0x10000
WS_MINIMIZEBOX      = 0x20000
WS_THICKFRAME       = 0x40000
WS_SYSMENU          = 0x80000
WS_CAPTION          = 0xC00000

WS_OVERLAPPEDWINDOW = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX

GetModuleHandle   = _GetModuleHandleA@4
GetStockObject    = _GetStockObject@4
LoadIcon          = _LoadIconA@8
LoadCursor        = _LoadCursorA@8
GetSystemMetrics  = _GetSystemMetrics@4
RegisterClassEx   = _RegisterClassExA@4
CreateWindowEx    = _CreateWindowExA@48
ShowWindow        = _ShowWindow@8
UpdateWindow      = _UpdateWindow@4
PeekMessage       = _PeekMessageA@20
GetMessage        = _GetMessageA@16
TranslateMessage  = _TranslateMessage@4
DispatchMessage   = _DispatchMessageA@4
InvalidateRgn     = _InvalidateRgn@12
ExitProcess       = _ExitProcess@4
BeginPaint        = _BeginPaint@8
EndPaint          = _EndPaint@8
GetClientRect     = _GetClientRect@8
CreateSolidBrush  = _CreateSolidBrush@4
SelectObject      = _SelectObject@8
Polygon           = _Polygon@12
DeleteObject      = _DeleteObject@4
DestroyWindow     = _DestroyWindow@4
PostQuitMessage   = _PostQuitMessage@4
DefWindowProc     = _DefWindowProcA@16
SetTimer          = _SetTimer@16
Sleep             = _Sleep@4

.macro MSG pre:req
  .bss
  .align 8
  \pre:
    \pre&.hwnd:     .int 0
    \pre&.message:  .int 0
    \pre&.wParam:   .int 0
    \pre&.lParam:   .int 0
    \pre&.time:     .int 0
    \pre&.pt.x:     .int 0
    \pre&.pt.y:     .int 0
  .text
.endm

.macro PAINTSTRUCT pre:req
  .bss
  .align 8
  \pre:
    \pre&.hdc:            .int 0
    \pre&.fErase:         .int 0
    \pre&.rcPaint.left:   .int 0
    \pre&.rcPaint.top:    .int 0
    \pre&.rcPaint.right:  .int 0
    \pre&.rcPaint.bottom: .int 0
    \pre&.fRestore:       .int 0
    \pre&.fIncUpdate:     .int 0
    \pre&.rgbReserved:    .fill 32
  .text
.endm

.macro POINT pre:req
  .bss
  .align 8
  \pre:
    \pre&.x: .int 0
    \pre&.y: .int 0
  .text
.endm

.macro RECT pre:req
  .bss
  .align 8
  \pre:
    \pre&.left:   .int 0
    \pre&.top:    .int 0
    \pre&.right:  .int 0
    \pre&.bottom: .int 0
  .text
.endm

.macro WNDCLASSEX pre:req
  .bss
  .align 8
  \pre:
    \pre&.cbSize:         .int 0
    \pre&.style:          .int 0
    \pre&.lpfnWndProc:    .int 0
    \pre&.cbClsExtra:     .int 0
    \pre&.cbWndExtra:     .int 0
    \pre&.hInstance:      .int 0
    \pre&.hIcon:          .int 0
    \pre&.hCursor:        .int 0
    \pre&.hbrBackground:  .int 0
    \pre&.lpszMenuName:   .int 0
    \pre&.lpszClassName:  .int 0
    \pre&.hIconSm:        .int 0
  .text
.endm

guitest.asm:

Code: Select all

.intel_syntax noprefix
.arch pentium
.altmacro
.include "macros.asm"
.include "guitest.inc"

/***************************************************************************************/

.data

    cong_seed:  .long 12345678
    szClass:    .asciz "test_class"
    szName:     .asciz "Test"

.bss

    .lcomm  hInst 4
    .lcomm  hWnd 4
    .lcomm  x 4
    .lcomm  y 4

.text

/***************************************************************************************/

.globl start
start:

    WNDCLASSEX  wcx
    MSG         msg

    invoke GetModuleHandle, 0
    mov hInst, eax
    mov dword ptr wcx.cbSize, 48
    mov dword ptr wcx.style, CS_BYTEALIGNWINDOW
    mov dword ptr wcx.lpfnWndProc, offset(WndProc)
    mov dword ptr wcx.cbClsExtra, 0
    mov dword ptr wcx.cbWndExtra, 0
    push hInst
    pop wcx.hInstance
    invoke GetStockObject, BLACK_BRUSH
    mov wcx.hbrBackground, eax
    mov dword ptr wcx.lpszMenuName,  0
    mov dword ptr wcx.lpszClassName, offset(szClass)
    invoke LoadIcon, 0, IDI_APPLICATION
    mov wcx.hIcon, eax
    invoke LoadCursor, 0, IDC_ARROW
    mov wcx.hCursor, eax
    mov dword ptr wcx.hIconSm, 0

    invoke RegisterClassEx, offset(wcx)

    W = 600
    H = 450
    invoke GetSystemMetrics, SM_CXSCREEN
    shr eax, 1
    sub eax, W / 2
    mov x, eax
    invoke GetSystemMetrics, SM_CYSCREEN
    shr eax, 1
    sub eax, H / 2
    mov y, eax

    xstyle = WS_EX_OVERLAPPEDWINDOW
    style = WS_OVERLAPPEDWINDOW
    invoke CreateWindowEx,xstyle,offset(szClass),offset(szName),style,x,y,W,H,0,0,hInst,0

    mov hWnd, eax
    invoke ShowWindow, hWnd, SW_SHOWNORMAL
    invoke UpdateWindow, hWnd

    invoke SetTimer, hWnd, 0, 30, 0

  msgLoop:

    invoke GetMessage, offset(msg), 0, 0, 0
    test eax, eax
    jz msgQuit
    invoke TranslateMessage, offset(msg)
    invoke DispatchMessage, offset(msg)
    jmp msgLoop

  msgQuit:

    invoke ExitProcess, msg.wParam

/***************************************************************************************/

.align 16
WndProc:

    PAINTSTRUCT ps
    POINT       pt1
    POINT       pt2
    POINT       pt3
    RECT        rc

    push ebp
    mov ebp, esp

    hwnd = 8; uMsg = 12; wParam = 16; lParam = 20

    cmp dword ptr [ebp+uMsg], WM_PAINT
    jne 1f
    invoke BeginPaint, [ebp+hwnd], offset(ps)
    invoke GetClientRect, [ebp+hwnd], offset(rc)
    invoke cong, 0xffffff
    invoke CreateSolidBrush, eax
    push eax
    invoke SelectObject, ps.hdc, eax
    push eax
    invoke cong, rc.right
    mov pt1.x, eax
    invoke cong, rc.bottom
    mov pt1.y, eax
    invoke cong, rc.right
    mov pt2.x, eax
    invoke cong, rc.bottom
    mov pt2.y, eax
    invoke cong, rc.right
    mov pt3.x, eax
    invoke cong, rc.bottom
    mov pt3.y, eax
    invoke Polygon, ps.hdc, offset(pt1), 3
    pop eax
    invoke SelectObject, ps.hdc, eax
    pop eax
    invoke DeleteObject, eax
    invoke EndPaint, [ebp+hwnd], offset(ps)
    jmp 5f
  1:
    cmp dword ptr [ebp+uMsg], WM_TIMER
    jne 2f
    invoke InvalidateRgn, hWnd, 0, 0
    jmp 5f
  2:
    cmp dword ptr [ebp+uMsg], WM_CLOSE
    jne 3f
    invoke DestroyWindow, [ebp+hwnd]
    jmp 5f
  3:
    cmp dword ptr [ebp+uMsg], WM_DESTROY
    jne 4f
    invoke PostQuitMessage, 0
    jmp 5f
  4:
    invoke DefWindowProc,[ebp+hwnd],[ebp+uMsg],[ebp+wParam],[ebp+lParam]
  5:
    leave
    ret 16

/***************************************************************************************/

// This is an asm implementation of a simple congruential generator
// by George Marsaglia, basically x(n)=69069*(n-1)+1234567.

.align 16
cong:

    push ebp
    mov ebp, esp

    base = 8

    mov eax, cong_seed
    mov ecx, 69069
    mul ecx
    add eax, 1234567
    mov cong_seed, eax
    xor edx, edx
    div dword ptr [ebp+base]
    mov eax, edx

    leave
    ret 4

/***************************************************************************************/

The EXE is 13,871 bytes.
Last edited by MichaelW on Mar 26, 2008 8:49, edited 1 time in total.

Return to “Windows”

Who is online

Users browsing this forum: No registered users and 5 guests