News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

64-bit Variadic functions

Started by Vortex, August 02, 2023, 05:19:52 AM

Previous topic - Next topic

Vortex

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

jj2007

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

Vortex

Hi Jochen,

No problem. By the way, I replaced the instruction db 0C3h with retn.

Caché GB

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
Caché GB's 1 and 0-nly language:MASM

zedd151

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?

HSE

Hi Vortex

buffer:dword,format:dword???
Equations in Assembly: SmplMath

Caché GB

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
Caché GB's 1 and 0-nly language:MASM

zedd151

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...

jj2007

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, number

In 64-bit land, mov reg32, offset somevar doesn't work any more.


Caché GB

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.
Caché GB's 1 and 0-nly language:MASM

jj2007

Quote from: Caché GB on August 02, 2023, 10:55:38 AM
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.

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).

Caché GB

Hi zedd
Yes, looking at Vortex's zip file made it clear. Always rescuing me, Thanks.

Hi jj
Thanks for checking.  :thumbsup:
Caché GB's 1 and 0-nly language:MASM

HSE

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.
Equations in Assembly: SmplMath

Vortex

Hi HSE,

Thanks, I fixed it. New attachment at the top.

Vortex

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.