News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Short Jumps and Far Jumps

Started by Zen, June 22, 2014, 05:05:25 AM

Previous topic - Next topic

Zen

I'm wondering, I've been reading the Intel documentation (Software Development Manuals) on jumps,...
Quote from: INTEL, Volume 2A: Instruction Set Reference, A-MNear and Short Jumps. When executing a near jump, the processor jumps to the address (within the current code segment) that is specified with the target operand. The target operand specifies either an absolute offset (that is an offset from the base of the code segment) or a relative offset (a signed displacement relative to the current value of the instruction pointer in the EIP register). A near jump to a relative offset of 8-bits (rel8) is referred to as a short jump. The CS register is not changed on near and short jumps.
Quote from: INTEL, Volume 2A: Instruction Set Reference, A-MA relative offset (rel8, rel16, or rel32) is generally specified as a label in assembly code, but at the machine code level, it is encoded as a signed 8-, 16-, or 32-bit immediate value. This value is added to the value in the EIP register. (Here, the EIP register contains the address of the instruction following the JMP instruction). When using relative offsets, the opcode (for short vs. near jumps) and the operand-size attribute (for near relative jumps) determines the size of the target operand (8, 16, or 32 bits).
Quote from: INTEL, Volume 2A: Instruction Set Reference, A-MFar Jumps in Real-Address or Virtual-8086 Mode. When executing a far jump in real-address or virtual-8086 mode, the processor jumps to the code segment and offset specified with the target operand. Here the target operand specifies an absolute far address either directly with a pointer (ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or m16:32). With the pointer method, the segment and address of the called procedure is encoded in the instruction, using a 4-byte (16-bit operand size) or 6-byte (32-bit operand size) far address immediate. With the indirect method, the target operand specifies a memory location that contains a 4-byte (16-bit operand size) or 6-byte (32-bit operand size) far address. The far address is loaded directly into the CS and EIP registers. If the operand-size attribute is 16, the upper two bytes of the EIP register are cleared.

What I'm wondering is: will the MASM compiler tell you when your JMP instruction should be a FAR Jump ???
I'm coding a rather long procedure, with contingency jumps all over the place, and I'm unsure how to calculate a near jump where the jump range is limited to –128 to +127 from the current EIP value.
Zen

RuiLoureiro

MASM compiler do it for you, i think.
If it is short MASM set it to short.
If not, set it to near (AFAIK in Win32).

dedndave

you mean NEAR
if it's win32, you shouldn't need FAR because the segment doesn't change

so, if you code
    jmp short some_label
the assembler will tell you that the relative jump is out of range
that means it needs to use the NEAR form

Zen

Thanks for the information.
It's kind of what I thought, because the code works correctly.
So,...a near jump is the default,...
Just out of curiosity,...if I indicate a FAR JUMP in my code (I'm unsure even of the syntax), do I indicate the segment somehow ???
Zen

dedndave

#4
you generally wouldn't indicate FAR unless it was a memory operand (it would be FAR PTR)
otherwise, the assembler knows which distance to use by the location of the target

haven't played with it much under win32 - no need for it

RuiLoureiro

FAR was used in DOS where one address
was DS:offset or ES:offset.
In Win32 the model is FLAT (ES=DS=SS).
Forget it.
I like to write   ...
                        jz             short  thisaddr

Then the assembler tel me: out of range in line X
and i remove the word "short".

jj2007

A FAR jump doesn't make sense in a flat memory model, so there is only the distinction between short and near - and the assembler decides for you, if you don't override the default. Simple example:

include \masm32\include\masm32rt.inc

.code
start:   test eax, eax
   je @F
   nop
@@:   test ecx, ecx
   je @F
   nops 128
@@:
   exit

end start

<ModuleEntryPoint>  Ú$  85C0           test eax, eax
00401002            ³. 74 01          jz short 00401005
00401004            ³.  90             nop
00401005            ³>  85C9           test ecx, ecx
00401007            ³. 0F84 80000000  jz 0040108D


As you can see, the short jump is 2 bytes long, the near one 6 bytes.

hutch--

I have played with the distinction of NEAR to SHORT and never ever found any speed difference. In the DOS days a few bytes may have mattered in COM files but the byte length of a jump simply does not matter in later OS designs.

As has already been said, a FAR jump is for a segmented memory model and not used in Win32 with its FLAT memory model.

dedndave

i have found it makes a difference in loops
if you can keep the loop small enough that the branch at the end (that loops back to the start) is SHORT,
it will run faster than if it has to be NEAR

also, if the loop ends with a SHORT branch,
alignment of the start of the loop doesn't seem to matter

but, if the loop ends with a NEAR branch,
it helps if the loop is 16-aligned

now - those are the results on a P4 core
perhaps the newer cores aren't as sensitive

i like developing code on a P4 because, if it runs well on mine, it will run well on most anything   :biggrin: