Hello,
Here is a sample of a 64-bit variadic function. A simple wsprintf emulator taking only the symbol % as format specifier.
; wsp V1.6 by Vortex - simple wsprintf emulator for NULL terminated strings
; Return value : eax holds the length of the string in the buffer
.data
wsp_table db 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.code
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
wsp PROC buffer:QWORD,format:QWORD,args:VARARG
; rcx -> buffer
; rdx -> format
; r8 -> args
sub rsp,8
mov QWORD PTR [rsp],rsi
mov QWORD PTR [rsp+8+8],rcx
mov QWORD PTR [rsp+24+8],r8
mov QWORD PTR [rsp+32+8],r9
lea r8,[rsp+24+8]
mov r9,1
sub rcx,r9
mov r11,OFFSET wsp_table
sub rdx,r9
@@:
add rcx,r9
loop1:
add rdx,r9
movzx rax,BYTE PTR [rdx]
mov BYTE PTR [rcx],al
cmp BYTE PTR [r11+rax],r9b
jne @b
test rax,rax
jnz @f
mov rax,rcx
sub rax,QWORD PTR [rsp+8+8]
mov rsi,QWORD PTR [rsp]
add rsp,8
retn
@@:
mov r10,QWORD PTR [r8]
xor rsi,rsi
@@:
movzx rax,BYTE PTR [r10+rsi]
mov BYTE PTR [rcx+rsi],al
add rsi,r9
test rax,rax
jnz @b
lea rcx,[rcx+rsi-1]
add r8,8
jmp loop1
wsp ENDP
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
END
I wonder why it complains about invoke:
*** Oops, I had not realised that we are in the PoAsm section - sorry, Erol! ***
*** assembling Test as Masm64 SDK source ***
Source C:\Masm64\Members\Erol\Test.asm
EntryPoint entry_point
Assembler ml64
Linker polink
-------
*** assembler options: [] ***
*** linker options: [], EP=[entry_point] ***
*** commandline: \Masm64\bin64\ml64.exe /c /nologo /FoC:\Masm64\Members\Erol\Tmp_file.obj C:\Masm64\Members\Erol\Tmp_file.asm ***
Assembling: C:\Masm64\Members\Erol\Tmp_file.asm
C:\Masm64\Members\Erol\Tmp_file.asm(16) : error A2008:syntax error
C:\Masm64\Members\Erol\Tmp_file.asm(18) : error A2008:syntax error : invoke
C:\Masm64\Members\Erol\Tmp_file.asm(21) : error A2008:syntax error : invoke
C:\Masm64\Members\Erol\Tmp_file.asm(23) : error A2008:syntax error : invoke
C:\Masm64\Members\Erol\Tmp_file.asm(25) : fatal error A1010:unmatched block nesting : entry_point
Hi Jochen,
No problem. By the way, I replaced the instruction db 0C3h with retn.
What am I doing wrong?
.data
szbuffer db 20 dup (0)
szFormat db "Yeah: %d", 0
number dd 12345
.code
main proc public
sub rsp, (5+2)*qword ; 38h
xor r9, r9
mov rdx, offset szFormat
mov rcx, offset szbuffer
if 0
mov r8d, number
call wsprintfA ; = "Yeah: 12345" correct
else
mov r8, offset number
call wsp ; = "Yeah: 90d" wrong
endif
xor r9d, r9d
xor r8d, r8d
lea rdx, szbuffer
xor ecx, ecx
call MessageBoxA
mov rcx, rax
call ExitProcess
ret
main endp
You are using offset for one, but not the other?
Possibly offset not needed...
If it is supposed to work like wsprintf, the args should be the same?
I don't use poasm so I can't test it, but that jumped out at me...
Also HSE in the next post has a point... hi Hector!
Probably was a conversion from 32 bit?
Hi Vortex
buffer:dword,format:dword???
Hi zedd
if I do this:
mov r8d, number
call wsp
the wsp call will crash.
This code is generic I think and will work with ml64 as well.
Hi HSE
If the "option prologue:none" and "option epilogue:none" directives are used, you can write what ever parameter list you want, it seems
wsp proc buffer:byte, format:byte, args:VARARG
As HSE suggested, maybe supposed to be qwords, not dwords.
We have to wait and see what Vortex's intentions were, as it is not very clear.
From Vortex's zip file in the first post
include Test.inc
.data
fmt db '% % %.',0
str1 db 'This is',0
str2 db 'a long',0
str3 db 'test',0
.data?
buffer db 128 dup(?)
.code
entry_point PROC PARMAREA=5*QWORD
invoke wsp,ADDR buffer,ADDR fmt,\
ADDR str1,ADDR str2,ADDR str3
invoke StdOut,ADDR buffer
invoke ExitProcess,0
entry_point ENDP
StdOut PROC string:QWORD PARMAREA=5*QWORD
; Function from the Masm64 package
; rcx = text address
LOCAL bwrt:QWORD
LOCAL _r14 :QWORD
LOCAL _r15 :QWORD
mov _r14,r14 ; preserve non-volatile registers
mov _r15,r15
mov r14,rcx ; store address in r14
mov rax,r14
sub rax,1
@@:
add rax,1
cmp BYTE PTR [rax],0 ; get the text length
jne @B
sub rax,r14 ; sub original address from RAX
mov r15,rax ; save string length into r15
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov rcx,rax
lea r9,bwrt
xor r10,r10
invoke WriteFile,rcx,r14,r15,r9,r10
mov r14,_r14 ; restore non-volatile registers
mov r15,_r15
mov rax,bwrt ; return value is bytes written
ret
StdOut ENDP
END entry_point
Quoteinvoke wsp,ADDR buffer,ADDR fmt, ADDR str1,ADDR str2,ADDR str3
The include file
wsp PROTO buffer:QWORD,format:QWORD,args:VARARG
StdOut PROTO :QWORD
ExitProcess PROTO :QWORD
GetStdHandle PROTO :QWORD
WriteFile PROTO :QWORD,:QWORD,:QWORD,:QWORD,:QWORD
STD_OUTPUT_HANDLE EQU -11
NULL equ 0
Maybe this may help...
Quote from: Caché GB on August 02, 2023, 09:42:13 AMWhat am I doing wrong?
Instead of...
mov r8, offset number
... use ...
lea r8, numberIn 64-bit land, mov reg32, offset somevar doesn't work any more.
Quote from: jj2007 on August 02, 2023, 10:24:39 AMlea r8, number
In 64-bit land, mov reg32, offset somevar doesn't work any more.
Hi jj
Yes it does.
OK I got it to work
.data
szbuffer db 100 dup (0)
fmt db '% % %.',0
str1 db "In 64-bit land ", 0
str2 db "it sill works ", 0
str3 db "any bets.",0
.code
mov rax, offset str3
mov qword ptr[rsp+20h], rax
mov r9, offset str2
mov r8, offset str1
mov rdx, offset fmt
mov rcx, offset szbuffer
call wsp
This function wsp does not format a dword to asscii.
Quote from: Caché GB on August 02, 2023, 10:55:38 AMQuote from: jj2007 on August 02, 2023, 10:24:39 AMlea r8, number
In 64-bit land, mov reg32, offset somevar doesn't work any more.
Hi jj
Yes it does.
You are right :thumbsup:
I had no time to test it, and I remembered that I used lea. Now I see that offset works, but it's 3 bytes longer than lea (in contrast to 32-bit land, where lea is one byte longer than offset).
Hi zedd
Yes, looking at Vortex's zip file made it clear. Always rescuing me, Thanks.
Hi jj
Thanks for checking. :thumbsup:
Quote from: jj2007 on August 02, 2023, 10:24:39 AMIn 64-bit land, mov reg32, offset somevar doesn't work any more.
Work perfectly if somevar is in .data section.
Hi HSE,
Thanks, I fixed it. New attachment at the top.
Hi Caché GB,
Talking about 64-bit Poasm coding, The keyword PARMAREA can be necessary in the producedure definions :
QuoteAMD64 only:
The optional PARMAREA = expression specifies the size of the parameter area. It must be specified if the procedure is calling other procedures, and must be the size of the largest parameter area passed to any procedure. It can be larger (will just waste space), but it may not be smaller. The expression must be a constant expression.
Here is a classical sample specifying the number of arguments :
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
CalcSum PROC counter:QWORD,args:VARARG
; mov QWORD PTR [rsp+8],rcx
mov QWORD PTR [rsp+16],rdx
mov QWORD PTR [rsp+24],r8
mov QWORD PTR [rsp+32],r9
xor rax,rax
lea r10,[rsp+16]
@@:
add rax,QWORD PTR [r10]
add r10,8
dec rcx
jnz @b
retn
CalcSum ENDP
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef