Last modified: Tue Jun 30 10:31:46 UTC+0200 2026 © A. Tarpai
JMP
8086 JMP
CPU fetches instruction bytes always from the address stored in CS and IP registers.
Then increments IP. CS stays unchanged. IP wraps around after FFFFh to 0000h.
IP always points to the next instruction.
The new IP- or CSIP is obtained either from the instruction (direct) or located in memory or register (indirect)
| direct | indirect | |
|---|---|---|
| Near: only IP modified | relative | indirect reg/mem |
| Far: both IP and CS modified | immediate | indirect mem |
For all non-relative addressing, the offset is absolute, i.e. reg/mem/imm value replaces IP or CS:IP.
| JMP opcodes bytes | syntax | ||||
|---|---|---|---|---|---|
| relative | near relative short | IP ± 128 | [EB][LO] | JMP rel8 | JMP only |
| near relative | IP ± 32KB | [E9][LO][HI] | JMP rel16 | ||
| absolute | near indirect reg | IP = 0..FFFF | [FF][RM] | JMP r16 | REG replaces IP |
| near indirect mem | IP = 0..FFFF | [FF][RM] | JMP m16 | points to [IP] [IP] | |
| far indirect mem | CS:IP = 0..1MB | [FF][RM] | JMP FAR m16 | points to [IP] [IP] [CS] [CS] | |
| far immediate | CS:IP = 0..1MB | [EA][IP][IP][CS][CS] | JMP i16:i16 | immediate replaces CS:IP |
386 JMP and EIP
EIP - the 386 CPU Instruction Pointer register is 32 bit. The CPU always uses the full EIP register content for code fetch – then increments EIP (for code-fetch, therefore, there is no 64K wrap-around in Real Mode and this will cause eventually exception).
The instruction's operand-size attribute (either implicit from D-bit or overridden by 66h prefix) determines whether
- EIP or IP is replaced and upper EIP zeroed
- 2- or 4 bytes read from memory for (E)IP for relative, immediate and memory indirect
- 16- or 32-bit register size used for (E)IP for register indirect
For relative offset the immediate value is sign-extended to 32-bit then added to EIP. If the operand-size attribute is 16, the upper two bytes of the EIP register are cleared. EIP = EIP AND 0000FFFFH – to emulate 8086's 64K wrap-around.
For absolute offset if the operand-size attribute is 16-bit - either from IMM, REG or MEM - the upper two bytes of the EIP register are cleared.
operand-size = 16 operand-size = 32
D=0 or D=1 and 66h D=1 or D=0 and 66h
31 0 31 0
+-------------------+ +-------------------+
| | EIP | | EIP
+-------------------+ +-------------------+
+--------------+----+ +--------------+----+
+ |ssssssssssss<-|s | REL8 |ssssssssssss<-|s | REL8
+--------------+----+ +--------------+----+
+---------+---------+ +-------------------+
+ |sssssss<-|s | REL16 |s | REL32
+---------+---------+ +-------------------+
| |
v v
+---------+---------+ +-------------------+
|000000000| | EIP | | EIP
+---------+---------+ +-------------------+
^ ^
| |
+---------+ +-------------------+
|[IP] [IP]| |[IP] [IP] [IP] [IP]|
+---------+ +-------------------+
^ ^
| |
r16 r32
m16 m32
i16 i32
Notes:
- Do not try to save codebytes in 32-bit mode and JMP WORD label. Upper EIP will be zeroed.
- Using operand-size = 32 in Real mode will effect the whole EIP. Should stay within 64K limit.
| operand-size | JMP opcodes bytes | syntax | |||
|---|---|---|---|---|---|
| relative | near relative short | 16 | EB LO | JMP rel8 | IP ± 128 |
| 32 | EB LO | JMP rel8 | EIP ± 128 | ||
| near relative | 16 | E9 LO HI | JMP rel16 | IP ± 32KB | |
| 32 | E9 LO LO LO HI | JMP rel32 | EIP ± 2GB | ||
| absolute | near indirect reg | 16 | FF RM | JMP r16 | REG replaces IP |
| 32 | FF RM | JMP r32 | REG replaces EIP | ||
| near indirect mem | 16 | FF RM | JMP m16 | points to [IP][IP] | |
| 32 | FF RM | JMP m32 | points to [IP][IP][IP][IP] | ||
| far indirect mem | 16 | FF RM | JMP FAR m16 | points to [IP][IP][CS][CS] | |
| 32 | FF RM | JMP FAR m32 | points to [IP][IP][IP][IP][CS][CS] | ||
| far immediate | 16 | EA IP IP CS CS | JMP i16:i16 | immediate replaces CS:IP | |
| 32 | EA IP IP IP IP CS CS | JMP i16:i32 | immediate replaces CS:EIP | ||
| When operand-size = 16, EIP = 0000_xxxx | |||||
JMP 16/32-bit Assembly
This is NASM.
NASM MOV - valid for JMP/CALL too: "Don't confuse the DWORD prefix outside the square brackets, which controls the size of the data stored at the address, with the one inside the square brackets which controls the length of the address itself."
[BITS 16]
; rel
EB(FF) jmp short -1 EIP = 0000 + d
E9(FFFF) jmp word -1 EIP = 0000 + d
66 E9(FFFFFFFF) jmp dword -1 EIP = EIP + d
; near indirect reg
FFE0 jmp ax EIP = 0000 AX
66 FFE0 jmp eax EIP = EAX
; near indirect mem
FF25 jmp [di] DI -> [IP] [IP] -> EIP = 0000 IP
FF25 jmp word [di] DI -> [IP] [IP] -> EIP = 0000 IP
67 FF27 jmp [edi] EDI -> [IP] [IP] -> EIP = 0000 IP
67 FF27 jmp word [edi] EDI -> [IP] [IP] -> EIP = 0000 IP
66 FF25 jmp dword [di] DI -> [IP] [IP] [IP] [IP] -> EIP
6667 FF27 jmp dword [edi] EDI -> [IP] [IP] [IP] [IP] -> EIP
; far indirect mem
FF2D jmp far [di] DI -> [IP] [IP] [CS] [CS] -> EIP = 0000 IP:CS
FF2D jmp word far [di] DI -> [IP] [IP] [CS] [CS] -> EIP = 0000 IP:CS
67 FF2F jmp far [edi] EDI -> [IP] [IP] [CS] [CS] -> EIP = 0000 IP:CS
67 FF2F jmp word far [edi] EDI -> [IP] [IP] [CS] [CS] -> EIP = 0000 IP:CS
66 FF2D jmp dword far [di] DI -> [IP] [IP] [IP] [IP] [CS] [CS] -> EIP:CS
6667 FF2F jmp dword far [edi] EDI -> [IP] [IP] [IP] [IP] [CS] [CS] -> EIP:CS
; far absolute
EA34120800 jmp 8:0x1234 [IP] [IP] [CS] [CS] -> EIP = 0000 IP:CS
EA34120800 jmp 8:word 0x1234 [IP] [IP] [CS] [CS] -> EIP = 0000 IP:CS
66 EA341200000800 jmp 8:dword 0x1234 [IP] [IP] [IP] [IP] [CS] [CS] -> EIP:CS
[BITS 32]
; rel
EB(FF) jmp short -1 EIP = EIP + d
E9(FFFFFFFF) jmp dword -1 EIP = EIP + d
66 E9(FFFF) jmp word -1 EIP = 0000 + d
; near indirect reg
FFE0 jmp eax EIP = EAX
66 FFE0 jmp ax EIP = 0000 AX
; near indirect mem
FF27 jmp [edi] EDI -> [IP] [IP] [IP] [IP] -> EIP
FF27 jmp dword [edi] EDI -> [IP] [IP] [IP] [IP] -> EIP
67 FF25 jmp [di] DI -> [IP] [IP] [IP] [IP] -> EIP
67 FF25 jmp dword [di] DI -> [IP] [IP] [IP] [IP] -> EIP
66 FF27 jmp word [edi] EDI -> [IP] [IP] -> EIP = 0000 IP
6667 FF25 jmp word [di] DI -> [IP] [IP] -> EIP = 0000 IP
; far indirect mem
FF2F jmp far [edi] EDI -> [IP] [IP] [IP] [IP] [CS] [CS] -> EIP:CS
FF2F jmp dword far [edi] EDI -> [IP] [IP] [IP] [IP] [CS] [CS] -> EIP:CS
67 FF2D jmp far [di] DI -> [IP] [IP] [IP] [IP] [CS] [CS] -> EIP:CS
67 FF2D jmp dword far [di] DI -> [IP] [IP] [IP] [IP] [CS] [CS] -> EIP:CS
66 FF2F jmp word far [edi] EDI -> [IP] [IP] [CS] [CS] -> EIP = 0000 IP:CS
6667 FF2D jmp word far [di] DI -> [IP] [IP] [CS] [CS] -> EIP = 0000 IP:CS
; far absolute
EA341200000800 jmp 8:0x1234 [IP] [IP] [IP] [IP] [CS] [CS] -> EIP:CS
EA341200000800 jmp 8:dword 0x1234 [IP] [IP] [IP] [IP] [CS] [CS] -> EIP:CS
66 EA34120800 jmp 8:word 0x1234 [IP] [IP] [CS] [CS] -> EIP = 0000 IP:CS