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 ?..
ramguru,
You can use MASM for x64, the assembler is called ml64.exe. There is some info about using it here (http://www.masm32.com/board/index.php?topic=10880.0). 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 (http://msdn.microsoft.com/en-us/library/ms794533.aspx)
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
drizz,
Thanks for the good info. :U
I'll have to give POASM a try with x64.
What about goasm ? Its 64bit support seems complete. I've never used it though.
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.
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
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
I'm wondering when we'll get an x64 compiler from Intel :bg
Welcome back Ramguru! :bg
Thank you :U
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 (http://www.jorgon.freeserve.co.uk) has a tutorial on 64-bit programming.
The subtitle is : 64-bit programming using the "Go" tools
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 :} )
Hi ramguru
You should also read about "RIP-relative addressing" :wink
change:
invoke dqtoa, num1, ADDR buf1
to
invoke dqtoa, num1[rip], ADDR buf1
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
ha-ha actually I was focusing on goasm starting yesterday. Indeed it has the most complete & user friendly 64bit support. Though I have to say documentation could be neater :} .. and lack of examples (just invoke MessageBox), but that's allright..
BTW I've found another bad poasm (x64) feature that was the last drop :}
let's assume we have the following code:
foo proc bla1:QWORD, bla2:QWORD
LOCAL hamster:QWORD
; bla1, bla2 are valid here
invoke MessageBox,...
; bla1, bla2 become invalid here
mov r10, bla1 ; --> mov r10, rcx
foo endp
It's simple really - poasm doesn't write any parameter to stack .. so they are lost if not preserved manually
That's what param area is for....
So this is the actual code:
foo proc bla1:QWORD, bla2:QWORD PARMAREA=4*QWORD
LOCAL hamster:QWORD
mov rcx, bla1
invoke MessageBox, 0, 0, 0, 0
mov rcx, bla1
ret
foo endp
And this is it's disassembly
sub_140001028 proc near ; CODE XREF: start+12
sub rsp, 38h
mov rcx, rcx
mov r9, 0 ; uType
mov r8, 0 ; lpCaption
mov rdx, 0 ; lpText
mov rcx, 0 ; hWnd
call MessageBoxA
mov rcx, rcx
add rsp, 38h
retn
sub_140001028 endp
It's not like I haven't checked before stating my opinion..
In ML64 arguments evaluate to stack and in poasm to Registers, so in ML64 you can save them with "mov bla1,rcx"
I don't know if there is an easy way to access param stack area with poasm, it's probably a good idea to ask Pelle about that.