I would like to use an absolute direct jump in my 32-bit flat program, but when I look in the Intel opcode reference manual it doesn't seem to exist such a jump? Why is this? I must have misunderstood something, right?

Clarification:

I would like a jmp-instruction of the following form:


<opcode byte(s)> <32-bit flat address to jump to>


But in the Intel manual I can only find indirect jumps with absolute addresses in the opcode!?
I.e., like this:


<opcode byte(s)> [<32-bit flat address to read jump address from>]



This leads to an extra step of indirection, which both wastes execution time and memory (the extra variable where the jump target address is stored) compared to if the absolute address would be stored inside the opcode itself.

I did find an opcode "Jump far, absolute, address given in operand", but this one wants an operand of the format ptr16:32, and what would I then put in the 16-bit segment part? Is such a call even legal in 32-bit flat code?

And I don't want to use relative addresses, because I want to have these jumps in trampoline-variables that can be moved in memory and still work.

What have I missed?

Any tips would be appreciated.

Thanks!
Posted on 2002-12-30 14:15:05 by dELTA
I think you are stuck with 2 instructions to branch to a specified address.


mov eax, address
jmp eax
--or--
push address
ret

Regards,

hutch@movsd.com
Posted on 2002-12-30 16:02:40 by hutch--
Ok, I see. But those alternatives you just suggested are practically as good as direct jumps anyway (second alternative is equal size to an instruction with 2 opcodes + 32-bit address, cool!), so they'll work great anyway. I didn't think of those options myself, thanks!
Posted on 2002-12-30 16:28:59 by dELTA
Hutch, Since were talking about jumps, I have a little question
for you. When I have jumps/calls directly after a call I replace the
jump/calls by changing the return address. Is this good for speed?
I think it saves some cpu time. I know it will give you a little less readability.

In my opinion its sounds logically that the next instruction is executed
instead of just returning to the same place and call it from there. Ill try to
show you what i mean.
[color=sienna]

push param.1
push param.1
call function1
push param.2
call function2
jmp label
[/color]

[color=sienna]

push param.2
push label ;return address
push param.1
push param.1
push function2 ;return address
jmp function1
[/color]

I would really like to hear any cons/pros when doing this.
Posted on 2002-12-30 16:30:16 by natas
About changing a CALL addr followed by a RET to a JMP addr, or doing a PUSH addr followed by a RET:
Some CPU's (e.g. the Pentium 4) have special optimizations (CALL/RET stack) that work as long as the CALLs and RETs are perfectly in pairs. So such tricks, that made code faster on previous CPU's, actually slow things down e.g. on the Pentium 4.
Posted on 2002-12-30 17:09:42 by Maverick

About changing a CALL addr followed by a RET to a JMP addr, or doing a PUSH addr followed by a RET:
Some CPU's (e.g. the Pentium 4) have special optimizations (CALL/RET stack) that work as long as the CALLs and RETs are perfectly in pairs. So such tricks, that made code faster on previous CPU's, actually slow things down e.g. on the Pentium 4.
Thanks for the info Maverick! :alright:
Posted on 2002-12-30 17:18:57 by natas
natas,
Let me see if I got your intention right. You want to start from a MAIN program, go to another program called F1, do some things there, jump to another program called F2, do some more things, and then return immediately to the main program without the extra overhead of returning to F1 before returning to the main program. That assumes you have no further processing to do in F1. Have I go that right?

It appears your example will work, but let's see if we can improve it a bit.




PUSH paramF1a ;need to push params
PUSH paramF1b ;can't get around that
CALL F1 ;CALL does a PUSH and JMP. It's smart to take advantage of that.
........ ;do your
........ ; thing in F1
PUSH paramF2a ;now we get ready to go to F2
JMP F2 ;this time we don't do a call, just a simple jump to F2, so no return address to F1 exists
........ ; do your
........ ; thing in F2
ADD ESP,1*4 ;ESP now points to the return address to MAIN
RET 2*4 ;return to MAIN is complete and stack is balanced, F1 return bypassed
;RET does a POP, JMP and SUB. It's wise to take advantange of that


Notice also that a CALL is paired with a RET.
Posted on 2002-12-30 22:08:32 by Ratch
natas,

I am much of the same view as Maverick, you mess up the CALL/RET pairing for very little purpose.

I am inclined to inline code that is that speed critical so there is no stack loss to worry about with CALL/RET and perhaps locals as well.

Regards,

hutch@movsd.com
Posted on 2002-12-31 03:43:36 by hutch--

I agree++, inlining is generally too much understimated.
Posted on 2002-12-31 04:19:26 by Maverick
Thanks again for the info on the subject! :alright: However, replacing
calls with jump(in my code) does increase the speed. Ofcourse this
will probably be different on other processors(I have an AMD K6-2 400Mhz).
The speed increase was only by 1.5 seconds anyway. ( :grin: ) So ill
probably stick with the normal calls. Im still going to experiement with
instructions. Who knows were it will take me? :alright:

dELTA: Sorry for talking a little offtopic here. Sometimes it just happens. ( ;) )
Posted on 2003-01-01 15:53:25 by natas



I did find an opcode "Jump far, absolute, address given in operand", but this one wants an operand of the format ptr16:32, and what would I then put in the 16-bit segment part?


:)
You would put value of CS as 16 bit part(selector).
(1Bh - NT, 227h - 9x)
Is such a call even legal in 32-bit flat code?


Of course it is legal. To say more you can not use it any
other then in 32 bit addressing mode.

IMO, you should study system aspects of protect mode before asking what is legal in flat mode.
Otherwise anything you get as an answer to your question you still will not be able to comprehend.
Posted on 2003-01-01 16:36:35 by The Svin