News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

VARARG and Procs

Started by Jimg, July 06, 2005, 04:39:29 PM

Previous topic - Next topic

Jimg

Yes, the AddNumbers routine would need to know that the value pushed on the stack was a 16-bit number.  Assuming it had some way to know that, it would work properly, but the stack would still be wrong.

Jimg

And now that I think about it a little more....
000000A5  51 push ecx ; save value for later
invoke AddNumbers,eax,4,dx,5
000000A6  6A 05    *     push   +000000005h
000000A8  6A 00    *     push   000h               ; what is this???
000000AA  66| 52    *     push   dx
000000AC  6A 04    *     push   +000000004h
000000AE  50    *     push   eax
000000AF  E8 00000066    *     call   AddNumbers
000000B4  83 C4 10    *     add    esp, 000000010h
000000B7  59 pop ecx


Why is there an extra zero dword pushed, and why would a routine know to expect this?

Jeff

that extra push was inserted because the procedure was expecting 32bit arguments when you passed in a 16bit argument.  then MASM tried to compensate for this so it (intends to) push 0 as a word.  tho it usually does a bad job at this.

the best thing to do is pass ALL dwords or make the necessary changes if you need smaller (zero extend the word into a 32bit register and pass the register for an argument).

rea

What I know about push is that the value substracted to (e)sp depend on the operation mode of the CPU, 16 or 32 bits, 16 bits = 2 bytes, 32 bits = 4 bytes.

Then I don't think that extra 0 is for compensate a 16 bit value pushed in the stack, also you can see here http://nasm.sourceforge.net/doc/html/nasmdocb.html#section-B.4.263 specific the first description line. tough like I see you say that is a bad work, and that is because is trying to do what already push do (compensate clearly if you push a 16 bit or 8 bit value in the stack) the necesary bytes for fill the correct dword starting at where esp was...



If you say... how the CPU inmediately try any value like a dword or word depending on the operation mode (for push/pop)????, see the encoding compared to the anterior reference

QuotePUSH imm8                     ; 6A ib                [186]

The codifications 6A followed by a inmediate byte, but if you execute this, it will be pushed a 32 bit value (expanded with zeros).



I guess or argee is a error of invoque... tought perhpas can be corrected.

Rifleman

Gentleman,
This is just my two cents.  I am not sure why


invoke AddNumbers,eax,4,dx,5


is used instead of


invoke AddNumbers,eax,4,edx,5


Because even if you prefer to operate on a 16bit value, what harm does it do to push it as 32bit so as to ensure that the stack is properly aligned.  I will reread the posts to make sure I am not missing something but IMO that seems to be the thing to do.  If AddNumbers expects a value in DX, it will just ignore the upper 16bits.

PBrennick

Rifleman

Gentleman,
In rereading the posts I see that Hutch has already posted a warning about this type of thing.  When it comes to macros used as preprocessors, Hutch is a real genius.  Remember that invoke is a macro and listen to Hutch.

Shucks, now I am up to four cents.
PBrennick

hutch--

 :red

I wish you were right. Variations in characteristics depending on which internal macro operator is used has nearly driven me nutz. Cute things like a FOR loop reinitialises an equae with txt in it if a mcro using the equate is called from within thr FOR loop.  :(
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Rifleman

Hi Hutch,
I don't want to get too far off topic but genius is a relative term and you do this stuff better than most of us.  Anyway, I think it is best to push EDX in this case.  I hope I got that right, at least.

PBrennick

Jimg

Yes, I agree about best to use edx. I was trying to account for every possibility in the routine I was working on, so am trying anything that can happen.  I was just pointing out a possible problem.  I was getting pretty trusting of invoke, even with it's shortcomings, but it's important that everyone know about this "feature". Does anyone know if this is fixed in versions later than 6.15? That's the latest one I have.
I may be talked into using a helper macro to call the routine just to avoid invoke :(

Rifleman

Jimq,
I doubt that they will fix what is not broke in their opinion (and mine).  Intentionally causing a stack imbalance will probably lead them to believe that the problem lies with who is causing the imbalance.  There is no offense implied here, when it comes to stretching the limits of the assembler, I am probably the worst offender because it has been so much a part of my life.  Having said that, though, when something blows up, I point the 'fickle finger of fate' at myself and repair the code.  :bg

PBrennick

Jimg

Hi Paul-

Well, I went over all the documentation I had, and it all seemed to indicate it should work.  So I went to msdn for the latest info-

QuoteINVOKE expression [[, arguments]]

Calls the procedure at the address given by expression, passing the arguments on the stack or in registers according to the standard calling conventions of the language type. Each argument passed to the procedure may be an expression, a register pair, or an address expression (an expression preceded by ADDR).
I'm still not sure what a register pair is in this context.  I always thought that was like eax:edx
so searching on register pair I found at
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmasm/html/vcerrA2033.asp
Quoteinvalid INVOKE argument : argument number

The INVOKE directive was passed a special 386 register, or a register pair containing a byte register or special 386 register. These registers are illegal with INVOKE.

It would have been nice to get this error comment.  There is no indication what version of masm this would occur with.

Jeff

#26
Quote from: Jimg on July 09, 2005, 04:35:15 PM
Hi Paul-

Well, I went over all the documentation I had, and it all seemed to indicate it should work. So I went to msdn for the latest info-

QuoteINVOKE expression [[, arguments]]

Calls the procedure at the address given by expression, passing the arguments on the stack or in registers according to the standard calling conventions of the language type. Each argument passed to the procedure may be an expression, a register pair, or an address expression (an expression preceded by ADDR).
I'm still not sure what a register pair is in this context. I always thought that was like eax:edx
so searching on register pair I found at
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmasm/html/vcerrA2033.asp
Quoteinvalid INVOKE argument : argument number

The INVOKE directive was passed a special 386 register, or a register pair containing a byte register or special 386 register. These registers are illegal with INVOKE.

It would have been nice to get this error comment. There is no indication what version of masm this would occur with.

i checked the MASM programmers guide and whenever they mention register pair, they were referring to a segment and GP register.  (see "Invoking Far Addresses")  to indicate a register pair, they used a double semicolon.  i played around with that idea for a bit and it looks like we can do 2 GP registers as well (eax::edx).
someproc PROTO STDCALL,:QWORD,:QWORD,:DWORD
.
.
.
    MOV eax,01234567h
    MOV edx,89ABCDEFh
    INVOKE someproc,eax::edx,edx::eax,ax::dx
.
.
.
someproc PROC STDCALL,a:QWORD,b:QWORD,c:DWORD
    ;a = 0123456789ABCDEFh
    ;b = 89ABCDEF01234567h
    ;c = 4567CDEFh
    RET
someproc ENDP

you may find that useful.  :)

[edit]
added stuff to clear things up.

Rifleman

Hi Jeff,
Yes, that is certainly useful.  I am certain I never tried that.

Paul

GregL

Jeff,

:U That is useful, I didn't know you could do that.



hutch--

Jim,

Here is a demo on how to handle a C calling convention procedure using the preprocessor to automatically handle pushing the variable number of arguments and correct the stack after. You need to get the latest macro file from the MASM2 subforum for the macros used but it gives you a clean and tidy way to handle a C calling convention procedure.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    tprint MACRO args:VARARG
      LOCAL acnt,lcnt                       ;; a couple of macro locals

      push esi                              ;; preserve ESI
      mov esi, alloc(16384)                 ;; allocate 16k of buffer

      acnt = argcount(args)                 ;; get the VARARG argument count
      lcnt = acnt                           ;; assign to a local var

      REPEAT acnt
        push repargof(getarg(lcnt,args))     ;; push variable number of args
        lcnt = lcnt - 1
      ENDM

      push esi                              ;; push the buffer address
      push argcount(args)                   ;; push the argument count
      call szMultiCat                       ;; call the C calling procedure
      add esp, argcount(args)*4+8           ;; correct the stack

      invoke StdOut, esi                    ;; display the text
      fn StdOut,chr$(13,10)                 ;; append a CRLF to display

      free esi                              ;; free the memory buffer
      pop esi                               ;; restore ESI
    ENDM

    .code

start:
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    call main

    inkey

    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    nops 3

    tprint "This ","is ","a test"

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start

DISASSEMBLY

    push esi
    push 4000h
    push 40h
    call fn_00401146
    mov esi, eax
    push 403021h
    push 403028h
    push 40302Ch
    push esi
    push 3
    call fn_00401070
    add esp, 14h
    push esi
    call fn_004010A0
    push 403032h
    call fn_004010A0
    push esi
    call fn_0040114C
    pop esi
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php