the simplest 64bit app won't start

Started by ramguru, June 07, 2009, 08:08:26 PM

Previous topic - Next topic

ramguru

hey everyone, I want to make a new start in asm programming.
Decided to write only 64bit applications from now on.
So as I can see masm won't be a tool of my choice.
Now poasm seems to have some support, or maybe I'm wrong...


    includelib \POASM\lib64\user32.lib

MessageBoxA PROTO :QWORD,:QWORD,:QWORD,:DWORD
       
    .data
ALIGN 8
dlgname db "TESTWIN",0
    .code

start:
ALIGN 8
invoke MessageBoxA, 0, ADDR dlgname, ADDR dlgname, 5

end start


compiler/linker parameters:

C:\POASM\bin\poasm /AAMD64 "%1.asm"
C:\POASM\bin\polink /MACHINE:AMD64 /SUBSYSTEM:WINDOWS "%1.obj"


The code compiles fine w/o a single warning, but once I start the app it crashes. Could anyone help with that ? Maybe I'm doing impossible ?..

GregL

#1
ramguru,

You can use MASM for x64, the assembler is called ml64.exe.  There is some info about using it here.  In your code, you should set up the Parameter Stack Area, which requires that you allocate at least 4 QWORDS on the stack, C compilers allocate at least 5 QWORDS.  I haven't used POASM for x64 yet, so I'm only speaking from MASM experience.  One thing I found really helpful is to look at the dissassembly of an x64 executable from a C compiler.

Here is the dissassembly from a simple 'Hello World' C program:

#include <stdio.h>

int main(void)
{
000000013F081000  sub         rsp,28h
    printf("Hello x64 world!\n");
000000013F081004  lea         rcx,[__native_dllmain_reason-3Ch (13F083000h)]
000000013F08100B  call        qword ptr [__imp_printf (13F0820F8h)]
    return 0;
000000013F081016  xor         eax,eax
}
000000013F081018  add         rsp,28h
000000013F08101C  ret           



The rules: Calling Convention for x64 64-Bit Environments



drizz

ramguru,
Read about the stack in x64. It must be aligned at 16 at all times.
You can put "and rsp,-16" on start since it's the entrypoint but you're going to be calling functions read about param area like Greg said.

Greg,
Poasm is better than ml64, It has a very useful PARMAREA command, invoke WORKS, does not have "proc stack alignment bug" like masm etc.

the fifth qword makes the stack aligned at 16 bytes.

Here is how it works:
Upon entrypoint stack is misaligned because "call" puts return address on the stack which is 8bytes.
Your/Compiler duty is to make stack aligned after the prologue to be aligned at 16 again, taking into consideraction local variables and preserved registers. Do not push a single register before calling a proc because that will make the stack mislaigned again. Stack must be aligned at 16 at all times. If you use poasm and follow this rules you wont have any problems
The truth cannot be learned ... it can only be recognized.

GregL

drizz,

Thanks for the good info.  :U

I'll have to give POASM a try with x64.


BlackVortex

What about goasm ? Its 64bit support seems complete. I've never used it though.

mitchi

And there is Sol_Asm too ! 64 bit worked perfectly last time I tried  :green
I'm really grateful to have good tools like this available to me.

dedndave

i bet instructions like....
mov rax,7
or
mov al,7
must cause actual physical pain in 64-bit - lol

my eye twitches as it is, in 32-bit

drizz

Heres a hello world for ramguru:
MessageBoxA PROTO :QWORD,:QWORD,:QWORD,:DWORD
MessageBox EQU <MessageBoxA>
ExitProcess PROTO :QWORD
       
.data
ALIGN 8
dlgname db "TESTWIN",0
.code

;; mainCRTStartup proc public; SUBSYSTEM:CONSOLE
;; WinMainCRTStartup proc public; SUBSYSTEM:WINDOWS

WinMainCRTStartup proc PARMAREA=4*QWORD;; MAX 4 arguments Are used in this proc
;push rax;;  DO NOT DO THIS, push 16 bytes or use locals
invoke MessageBox,0,ADDR dlgname,ADDR dlgname,5
;pop rax
invoke ExitProcess,rax
WinMainCRTStartup endp

end
The truth cannot be learned ... it can only be recognized.

mitchi

I'm wondering when we'll get an x64 compiler from Intel  :bg

Mark Jones

"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

ramguru


Vortex

Quote from: BlackVortex on June 07, 2009, 11:35:00 PM
What about goasm ? Its 64bit support seems complete. I've never used it though.

Jeremy's website has a tutorial on 64-bit programming.

The subtitle is : 64-bit programming using the "Go" tools

ramguru

I'm kinda heaving a hard start :}
polink will complain about every global variable that is declared in .data section
f.e.

    .data
num1 dq 0FF00FF00FF00FF00h
    .code

WinMainCRTStartup proc PARMAREA=4*QWORD
LOCAL buf1[32]:BYTE

invoke dqtoa, num1, ADDR buf1

invoke MessageBoxA, 0, ADDR buf1, ADDR buf1, 0

WinMainCRTStartup endp

; main idea is nothing new:
; 1) divide by 10
; 2) append (remainder + '0') to string
; 3) shift string (because we appended from the end)
dqtoa proc num:QWORD, buf:QWORD

mov    rsi, 20 ; let's assume that our string cannot exceed 20 chars
mov    rdi, buf
mov    rax, num
mov    rcx, 10

@convert:
xor    rdx, rdx
test   rax, rax
jz     @done_convert
div    rcx
add    dl, '0'
mov    BYTE PTR [rdi+rsi], dl
dec    rsi
jmp    @convert
@done_convert:
mov    BYTE PTR [rdi+rsi], 0

mov    rcx, 20 
sub    rcx, rsi ; rcx - length of the string
inc    rsi      ; rsi - value by which we need to shift the string
@shift:
mov    al, BYTE PTR [rdi+rsi]
mov    BYTE PTR [rdi], al
test   al, al
jz     @done_shift
inc    rdi
jmp    @shift
@done_shift:
mov    rax, rcx
ret
dqtoa endp

produce the following error report:

POLINK: error: Relocation type ADDR32 is invalid without /LARGEADDRESSAWARE:NO, for symbol 'num1'.


But putting /LARGEADDRESSAWARE:NO means executable file cannot handle addresses above 2 GB which doesn't correspond to 64bit programming logic IMO (even though it compiles fine then :} )

drizz

Hi ramguru

You should also read about "RIP-relative addressing"  :wink

change:
invoke dqtoa, num1, ADDR buf1
to
invoke dqtoa, num1[rip], ADDR buf1
The truth cannot be learned ... it can only be recognized.

ecube

GoAsm 64bit support is beautiful, you can compile the same source for 32bit/64bit easily, example are here http://www.masm32.com/board/index.php?topic=11180.0, MASM64 is a joke btw, on so many levels. PoASM the author doesn't really care about Assembler, he's more C focused, GoASM is your best bet, I translated most my masm 32bit/64bit sources to GoASM and I couldn't be happier. Here's an example from the sdk

#DEFINE LINKFILES

;#Define WIN64 ;uncomment to enable for 64bit building
#include "\GoAsm\include\windows.h"

CODE SECTION

START:
#ifndef WIN64
    invoke MessageBox,0,"i'm running in 32bit!","i'm running in 32bit!",MB_ICONINFORMATION
#else
    invoke MessageBox,0,"i'm running in 64bit!","i'm running in 64bit!",MB_ICONINFORMATION
#endif
invoke ExitProcess,0