Author Topic: 64-bit BIN output format  (Read 186 times)

aw27

  • Member
  • ****
  • Posts: 852
  • Let's Make ASM Great Again!
64-bit BIN output format
« on: October 08, 2017, 11:06:47 PM »
I was adapting the Win32_5.asm of the Samples folder for 64-bit, which makes an .exe using the BIN output format.
Although, in the end I managed to do it using raw assembly language, there are a few shortcomings in the way UASM deals with the 64-bit case, namely:
1) Prototypes require a Language Specifier. If I enter FASTCALL it assumes it is 32-bit FASTCALL.
2) Default Prologues and Epilogues do not exist.
3) LOCAL is not recognized although does not produce error.
4) INVOKES work as if 32-bit FASTCALL was in force.

Please have a look at the comments in the source for further clarification.

Updated to allow importing from 2 DLLs and use the MessageBoxA as well. Required a few fixes in the macros.

johnsa

  • Member
  • ****
  • Posts: 583
    • Uasm
Re: 64-bit BIN output format
« Reply #1 on: October 09, 2017, 10:33:13 PM »
Hi,

Please try the following:

www.terraspace.co.uk/uasm242.zip

BIN output now supports use of  OPTION stackbase and win64. When this is used the assumption then is that the language type and ABIs conform to win64 and as such prologue/default langtype/locals should all work as expected for a 64bit windows app.

Code: [Select]
; uasm64 -bin -Fo bin64.exe bin64.asm
.x64
option casemap:none
option stackbase:rbp
option win64:7

.nolist
include winnt64.inc   ; Modification for 64-bit of winnt.inc from Sample folder of UASM.
.list

STD_OUTPUT_HANDLE equ -11
HANDLE typedef ptr 
HWND typedef ptr 
NULL equ 0

IMAGEBASE equ 140000000h
_IMAGE equ 0

PEHDR segment dword FLAT

;--- define the DOS "MZ" header

    ORG _IMAGE

    IMAGE_DOS_HEADER <"ZM", 80h, 1, 0,4,0,-1,0,200h,0,0,0,0,0,<0>,0,0,<0>,IMAGEREL PEHdr>

    db 0Eh         ;push cs
    db 1Fh         ;pop ds
    db 0BAh,0Eh,0  ;mov dx,text
    db 0B4h,09h    ;mov ah,9
    db 0CDh,21h    ;int 21h
    db 0B8h,01h,4Ch;mov ax,4c01h
    db 0CDh,21h    ;int 21h
    db "This program cannot be run in DOS mode",13,10,'$'

    ORG _IMAGE+80h

;--- define the Win32 "PE" header

PEHdr label byte
    db "PE",0,0
    IMAGE_FILE_HEADER <IMAGE_FILE_MACHINE_AMD64, num_sections, 0, 0, 0, sizeof IMAGE_OPTIONAL_HEADER64,\
        IMAGE_FILE_RELOCS_STRIPPED or IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_LARGE_ADDRESS_AWARE or IMAGE_FILE_LOCAL_SYMS_STRIPPED>

    IMAGE_OPTIONAL_HEADER64 { 20Bh, ;magic
        0Eh,0Ah,                        ;linker major, minor
        1000h,1000h,0,              ;sizeof code, initialized data, uninitialized data
        IMAGEREL startapp,    ;entry point
        IMAGEREL start_text,  ;baseof code
        IMAGEBASE,    ;imagebase
        1000h,200h,   ;section alignment, file alignment
        6,0,          ;OS major, minor
        0,0,          ;Image major, minor
        6,0,          ;Subsys major, minor
        0,            ;win32 version
        3000h,        ;sizeof image
        1000h,        ;sizeof header
        0,            ;checksum
        IMAGE_SUBSYSTEM_WINDOWS_CUI,
        0,            ;dll characteristics
        100000h,1000h,;stack res,com
        100000h,1000h,;heap res, com
        0,            ;loader flags
        16,           ;number of directories
        < <0,0>,\        ;0 exports
        < IMAGEREL start_idata, SECTIONREL endof_idata >,\ ;1 imports
        <0,0>,<0,0>,\    ;2 resource, 3 exception
        <>,<>,<>,<>,\    ;4 security, 5 baserelocs, 6 debug, 7 architecture
        <>,<>,<>,<>,\    ;8 globalptr, 9 tls, 10 load_config, 11 bound_import
        <>,<>,<>,<> >}   ;12 iat, 13 delay_import, 14 com descriptor, 15 reserved

;--- define the section table

sectiontable label byte
    IMAGE_SECTION_HEADER <".text", <sizeof_text>, IMAGEREL start_text, sizeof_text,\
        200h, 0, 0, 0, 0, 060000020h >
    IMAGE_SECTION_HEADER <".rdata", <SECTIONREL endof_idata+ sizeof_const>, IMAGEREL start_rdata, SECTIONREL endof_idata+ sizeof_const,\
        400h, 0, 0, 0, 0, 040000040h >
num_sections equ ( $ -  sectiontable ) / sizeof IMAGE_SECTION_HEADER

    ORG _IMAGE+200h   ;forces physical size of header to 200h and sets VA to 400200h

PEHDR ends

ALIGN1 segment dword public FLAT 'DATA'
    ORG 0E00h   ; change pc to RVA 1000h
ALIGN1 ends

_TEXT segment dword public FLAT 'CODE'
_TEXT ends

ALIGN2 segment dword public FLAT 'DATA'
    ORG 0E00h   ; change pc to RVA 2000h
ALIGN2 ends

_IDATA segment dword public FLAT 'DATA'
start_rdata label byte
start_idata label byte
;--- import descriptors go here
_IDATA ends
_IDATA$1 segment dword public FLAT 'DATA'
    IMAGE_IMPORT_DESCRIPTOR <<0>,0,0,0,0>
;--- ILT entries go here
_IDATA$1 ends
_IDATA$2 segment dword public FLAT 'DATA'
    dq 0    ;--- end of last ILT
;--- IAT entries go here
_IDATA$2 ends
_IDATA$3 segment dword public FLAT 'DATA'
    dd 0    ;--- end of last IAT
;--- import name strings go here
_IDATA$3 ends
_IDATA$4 segment dword public FLAT 'DATA'
endof_idata equ $
_IDATA$4 ends

CONST segment dword public FLAT 'DATA'
start_const label byte
CONST ends

DefineImpDll macro name
_IDATA segment
    IMAGE_IMPORT_DESCRIPTOR <<IMAGEREL name&ILT>,0,0,IMAGEREL name, IMAGEREL name&IAT>
_IDATA ends
_IDATA$1 segment
ifdef ImportDefined
    dq 0  ;terminate previous ILT
endif
name&ILT label dword
_IDATA$1 ends
_IDATA$2 segment
ifdef ImportDefined
    dq 0  ;terminate previous IAT
endif
name&IAT label dword
_IDATA$2 ends
_IDATA$3 segment
name db @CatStr(!",name, !"),0
    align 4
_IDATA$3 ends
ImportDefined equ 1
    endm

DefineImport macro name
_IDATA$1 segment
    dq IMAGEREL n&name
_IDATA$1 ends
_IDATA$2 segment
lp&name typedef ptr pr&name
name    lp&name IMAGEREL n&name
_IDATA$2 ends
_IDATA$3 segment
n&name dw 0
    db @CatStr(!",name, !"),0
    align 4
_IDATA$3 ends
    endm

; When the FASTCALL specifier is not there it reports error LANGUAGE specifier is not there.
; If FASTCALL is there, as is now, it assumes 32-bit FASTCALL not the 64-bit ABI
; I placed FASTCALL just to make it assemble because it will not be possible to use INVOKE correctly.     
prWriteConsoleA typedef proto :HANDLE, :ptr, :dword, :ptr, :ptr
prGetStdHandle  typedef proto :dword
prExitProcess   typedef proto :dword

    DefineImpDll kernel32
    DefineImport ExitProcess
    DefineImport WriteConsoleA
    DefineImport GetStdHandle

;if 0 ;if further dlls are to be imported
prMessageBoxA   typedef proto :HWND, :ptr, :ptr, :dword

    DefineImpDll user32
    DefineImport MessageBoxA
;endif

CONST segment

string1  db 13,10,"hello, Console World.",13,10
string2  db "hello, Windows World.",0
caption db "Hello",0

sizeof_const equ $ - start_const

CONST ends

_TEXT segment

start_text label near
;--- start of program

; ***Procedures build without PROLOGUEs or EPILOGUEs***
main proc
LOCAL dwWritten:dword
LOCAL hConsole:HANDLE
invoke  GetStdHandle, STD_OUTPUT_HANDLE
    mov hConsole, rax
invoke  WriteConsoleA, hConsole, addr string1, sizeof string1, addr dwWritten, NULL
    ret
main endp

;--- entry

startapp proc
    call main
    mov rcx,0
    lea rdx, string2
    lea r8, caption
    mov r9, 0
    sub rsp, 20h
    call MessageBoxA
    add rsp 20h
    xor rcx, rcx   
    call  ExitProcess
startapp endp

sizeof_text equ $ - start_text

    ORG 200h    ;align size of _TEXT to next 512 byte boundary
_TEXT ends

end

aw27

  • Member
  • ****
  • Posts: 852
  • Let's Make ASM Great Again!
Re: 64-bit BIN output format
« Reply #2 on: October 10, 2017, 03:10:59 AM »
It works!  :t