News:

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

make ret AX instruction

Started by Rockphorr, December 27, 2010, 07:06:18 AM

Previous topic - Next topic

Rockphorr

Now i can done it so:


lea BX,$exit
mov CS:[BX+1],AX

$exit:
BYTE 0CAh ;opcode(retf)
WORD 0


but may be exist opcode(ret AX)  like exist call AX

My target is the routine like printf which ax param is number of stack params.
Strike while the iron is hot - Бей утюгом, пока он горячий

japheth

Quote from: Rockphorr on December 27, 2010, 07:06:18 AM
Now i can done it so:


lea BX,$exit
mov CS:[BX+1],AX

$exit:
BYTE 0CAh ;opcode(retf)
WORD 0


Yes. But be aware that self-modifying code on recent cpus may slow down execution significantly!

Quote
but may be exist opcode(ret AX)  like exist call AX

No. But you may "simulate" such an instruction if you've got a free register:
      pop cx
      add sp,ax
      jmp cx

This sequence "destroys" the flags, though.

sinsi

Quote from: japhethNo. But you may "simulate" such an instruction if you've got a free register:
      pop cx
      add sp,ax
      jmp cx
But he uses a far return which complicates things a bit.

Quote from: japhethBut be aware that self-modifying code on recent cpus may slow down execution significantly!
Is that an issue with real mode code?



  mov cs:[pcount],ax
  ...
  db 0cah
pcount dw 0

This type of code will have problems in a "PROC USES EBX" situation though, since no "ret" appears.
Light travels faster than sound, that's why some people seem bright until you hear them.

dedndave

#3
if you want to preserve the flags, use LEA instead of ADD   :U
also, to preserve CX contents as well...
        pop     [sp+ax+2]  ;not sure this works - lol - i know it won't work on 8088
        lea     sp,[sp+ax]
        ret

you may have to play with it a bit, but you get the idea
for a FAR PROC, you'll need 2 POP's

dedndave

#4
looks like a new toy for lingo - lol
        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

SomeProc PROC Parm1:DWORD,Parm2:DWORD,Parm3:DWORD

        mov     ecx,[esp+12]
        pop     [esp+12]
        pop     eax
        pop     edx
;
;
;
;
;
        ret

SomeProc ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

anyways - you could apply something similar in 16-bit code...
where you make the adjustment at the beginning of the routine instead of at the end

japheth

Quote from: dedndave on December 27, 2010, 12:20:45 PM
if you want to preserve the flags, use LEA instead of ADD   :U
also, to preserve CX contents as well...
        pop     [sp+ax+2]  ;not sure this works - lol - i know it won't work on 8088
        lea     sp,[sp+ax]
        ret


This won't work, since neither SP nor AX are valid base- or index-registers.

And worse, you can't use the 32-bit counterparts either:

        movzx esp,sp
        movzx eax,ax
        pop     [esp+eax+2]  ;not sure this works - lol - i know it won't work on 8088
        lea     esp,[esp+eax]
        ret


because the highword of ESP is trashed "randomly" in 16-bit code under Windows.

dedndave

thanks Andreas

certainly, he could do something similar to this
        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

SomeProc PROC FAR Parm1:WORD,Parm2:WORD,Parm3:WORD

        mov     dx,[sp+6]      ;get Parm2
        mov     cx,[sp+8]      ;get Parm3
        pop     [sp+6]         ;RET offset to Parm2
        pop     [sp+6]         ;RET segment to Parm3
        push    cx             ;maybe not needed - if you only need to grab Parm3 once
        push    dx             ;maybe not needed - if you only need to grab Parm2 once
;
;
;
;
;
        lea     sp,[sp+6]      ;discard 3 parms below RETF address
        ret                    ;RETF

SomeProc ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef


or this
        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

SomeProc PROC FAR Parm1:WORD,Parm2:WORD,Parm3:WORD

        mov     dx,[sp+6]      ;get Parm2
        mov     cx,[sp+8]      ;get Parm3
        pop     [sp+6]         ;RET offset to Parm2
        pop     [sp+6]         ;RET segment to Parm3
        pop     ax
;
;AX = Parm1
;CX = Parm3
;DX = Parm2
;
;
;parms are already removed from stack
;
        ret                    ;RETF

SomeProc ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

dedndave

another approach, that might be a bit cleaner, is to use cdecl calling convention, making the caller responsible for stack clean-up   :P