Opcode |
Instruction |
Description |
---|---|---|
E8 cw |
CALL rel16 |
Call near, relative, displacement relative to next instruction |
E8 cd |
CALL rel32 |
Call near, relative, displacement relative to next instruction |
FF /2 |
CALL r/m16 |
Call near, absolute indirect, address given in r/m16 |
FF /2 |
CALL r/m32 |
Call near, absolute indirect, address given in r/m32 |
9A cd |
CALL ptr16:16 |
Call far, absolute, address given in operand |
9A cp |
CALL ptr16:32 |
Call far, absolute, address given in operand |
FF /3 |
CALL m16:16 |
Call far, absolute indirect, address given in m16:16 |
FF /3 |
CALL m16:32 |
Call far, absolute indirect, address given in m16:32 |
Saves procedure linking information on the stack and branches to the procedure (called procedure) specified with the destination (target) operand. The target operand specifies the address of the first instruction in the called procedure. This operand can be an immediate value, a general-purpose register, or a memory location.
This instruction can be used to execute four different types of calls:
Near call--A call to a procedure within the current code segment (the segment currently pointed to by the CS register), sometimes referred to as an intrasegment call.
Far call--A call to a procedure located in a different segment than the current code segment, sometimes referred to as an intersegment call.
Inter-privilege-level far call--A far call to a procedure in a segment at a different privilege level than that of the currently executing program or procedure.
Task switch--A call to a procedure located in a different task.
The latter two call types (inter-privilege-level call and task switch) can only be executed in protected mode. See the section titled "Calling Procedures Using Call and RET" in Chapter 6 of the IA-32 Intel(R) Architecture Software Developer's Manual, Volume 1, for additional information on near, far, and inter-privilege-level calls. See Chapter 6, Task Management, in the IA-32 Intel(R) Architecture Software Developer's Manual, Volume 3, for information on performing task switches with the CALL instruction.
Near Call. When executing a near call, the processor pushes the value of the EIP register (which contains the offset of the instruction following the CALL instruction) onto the stack (for use later as a return-instruction pointer). The processor then branches to the address in the current code segment specified with the target operand. The target operand specifies either an absolute offset in the code segment (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, which points to the instruction following the CALL instruction). The CS register is not changed on near calls.
For a near call, an absolute offset is specified indirectly in a general-purpose register or a memory location (r/m16 or r/m32). The operand-size attribute determines the size of the target operand (16 or 32 bits). Absolute offsets are loaded directly into the EIP register. If the operand-size attribute is 16, the upper two bytes of the EIP register are cleared to 0s, resulting in a maximum instruction pointer size of 16 bits. (When accessing an absolute offset indirectly using the stack pointer [ESP] as a base register, the base value used is the value of the ESP before the instruction executes.)
A relative offset (rel16 or rel32) is generally specified as a label in assembly code, but at the machine code level, it is encoded as a signed, 16- or 32-bit immediate value. This value is added to the value in the EIP register. As with absolute offsets, the operand-size attribute determines the size of the target operand (16 or 32 bits).
Far Calls in Real-Address or Virtual-8086 Mode. When executing a far call in real-address or virtual-8086 mode, the processor pushes the current value of both the CS and EIP registers onto the stack for use as a return-instruction pointer. The processor then performs a "far branch" to the code segment and offset specified with the target operand for the called procedure. 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 offset 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 operand-size attribute determines the size of the offset (16 or 32 bits) in the 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 to 0s.
Far Calls in Protected Mode. When the processor is operating in protected mode, the CALL instruction can be used to perform the following three types of far calls:
Far call to the same privilege level. Far call to a different privilege level (inter-privilege level call). Task switch (far call to another task).
In protected mode, the processor always uses the segment selector part of the far address to access the corresponding descriptor in the GDT or LDT. The descriptor type (code segment, call gate, task gate, or TSS) and access rights determine the type of call operation to be performed.
If the selected descriptor is for a code segment, a far call to a code segment at the same privilege level is performed. (If the selected code segment is at a different privilege level and the code segment is non-conforming, a general-protection exception is generated.) A far call to the same privilege level in protected mode is very similar to one carried out in real-address or virtual-8086 mode. 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). The operand-size attribute determines the size of the offset (16 or 32 bits) in the far address. The new code segment selector and its descriptor are loaded into CS register, and the offset from the instruction is loaded into the EIP register.
Note that a call gate (described in the next paragraph) can also be used to perform far call to a code segment at the same privilege level. Using this mechanism provides an extra level of indirection and is the preferred method of making calls between 16-bit and 32-bit code segments.
When executing an inter-privilege-level far call, the code segment for the procedure being called must be accessed through a call gate. The segment selector specified by the target operand identifies the call gate. Here again, the target operand can specify the call gate segment selector either directly with a pointer (ptr16:16 or ptr16:32) or indirectly with a memory location (m16:16 or m16:32). The processor obtains the segment selector for the new code segment and the new instruction pointer (offset) from the call gate descriptor. (The offset from the target operand is ignored when a call gate is used.) On inter-privilege-level calls, the processor switches to the stack for the privilege level of the called procedure. The segment selector for the new stack segment is specified in the TSS for the currently running task. The branch to the new code segment occurs after the stack switch. (Note that when using a call gate to perform a far call to a segment at the same privilege level, no stack switch occurs.) On the new stack, the processor pushes the segment selector and stack pointer for the calling procedure's stack, an (optional) set of parameters from the calling procedures stack, and the segment selector and instruction pointer for the calling procedure's code segment. (A value in the call gate descriptor determines how many parameters to copy to the new stack.) Finally, the processor branches to the address of the procedure being called within the new code segment.
Executing a task switch with the CALL instruction, is somewhat similar to executing a call through a call gate. Here the target operand specifies the segment selector of the task gate for the task being switched to (and the offset in the target operand is ignored.) The task gate in turn points to the TSS for the task, which contains the segment selectors for the task's code and stack segments. The TSS also contains the EIP value for the next instruction that was to be executed before the task was suspended. This instruction pointer value is loaded into EIP register so that the task begins executing again at this next instruction.
The CALL instruction can also specify the segment selector of the TSS
directly, which eliminates the indirection of the task gate. See Chapter
6, Task
Management, in the IA-32 Intel
Note that when you execute at task switch with a CALL instruction, the
nested task flag (NT) is set in the EFLAGS register and the new TSS's
previous task link field is loaded with the old tasks TSS selector. Code
is expected to suspend this nested task by executing an IRET instruction,
which, because the NT flag is set, will automatically use the previous
task link to return to the calling task. (See "Task Linking"
in Chapter 6 of the IA-32 Intel
Mixing 16-Bit and 32-Bit Calls. When making far calls between 16-bit and 32-bit code segments, the calls should be made through a call gate. If the far call is from a 32-bit code segment to a 16-bit code segment, the call should be made from the first 64 KBytes of the 32-bit code segment. This is because the operand-size attribute of the instruction is set to 16, so only a 16-bit return address offset is saved. Also, the call should be made using a 16-bit call gate so that 16-bit values will be pushed on the stack. See Chapter 16, Mixing 16-Bit and 32-Bit Code, in the IA-32 Intel(R) Architecture Software Developer's Manual, Volume 3, for more information on making calls between 16-bit and 32-bit code segments.
IF near call
THEN IF near relative call
IF the instruction pointer is not within code segment limit THEN #GP(0);
FI;
THEN IF OperandSize
32
THEN
IF stack not large enough for a 4-byte return address THEN #SS(0); FI;
Push(EIP);
EIP EIP + DEST; (*
DEST is rel32 *)
ELSE (* OperandSize
16 *)
IF stack not large enough for a 2-byte return address THEN #SS(0); FI;
Push(IP);
EIP (EIP + DEST)
AND 0000FFFFH; (* DEST is rel16
*)
FI;
FI;
ELSE (* near absolute call *)
IF the instruction pointer is not within code segment limit THEN #GP(0);
FI;
IF OperandSize 32
THEN
IF stack not large enough for a 4-byte return address THEN #SS(0); FI;
Push(EIP);
EIP DEST; (* DEST
is r/m32 *)
ELSE (* OperandSize
16 *)
IF stack not large enough for a 2-byte return address THEN #SS(0); FI;
Push(IP);
EIP DEST AND 0000FFFFH;
(* DEST is r/m16 *)
FI;
FI:
FI;
IF far call AND (PE
0 OR (PE 1 AND
VM 1)) (* real-address
or virtual-8086 mode *)
THEN
IF OperandSize 32
THEN
IF stack not large enough for a 6-byte return address THEN #SS(0); FI;
IF the instruction pointer is not within code segment limit THEN #GP(0);
FI;
Push(CS); (* padded with 16 high-order bits *)
Push(EIP);
CS DEST[47:32];
(* DEST is ptr16:32 or [m16:32] *)
EIP DEST[31:0]; (*
DEST is ptr16:32 or [m16:32]
*)
ELSE (* OperandSize
16 *)
IF stack not large enough for a 4-byte return address THEN #SS(0); FI;
IF the instruction pointer is not within code segment limit THEN #GP(0);
FI;
Push(CS);
Push(IP);
CS DEST[31:16];
(* DEST is ptr16:16 or [m16:16] *)
EIP DEST[15:0]; (*
DEST is ptr16:16 or [m16:16]
*)
EIP EIP AND 0000FFFFH;
(* clear upper 16 bits *)
FI;
FI;
IF far call AND (PE
1 AND VM 0) (*
Protected mode, not virtual-8086 mode *)
THEN
IF segment selector in target operand null THEN #GP(0); FI;
IF segment selector index not within descriptor table limits
THEN #GP(new code segment selector);
FI;
Read type and access rights of selected segment descriptor;
IF segment type is not a conforming or nonconforming code segment, call
gate,
task gate, or TSS THEN #GP(segment selector); FI;
Depending on type and access rights
GO TO CONFORMING-CODE-SEGMENT;
GO TO NONCONFORMING-CODE-SEGMENT;
GO TO CALL-GATE;
GO TO TASK-GATE;
GO TO TASK-STATE-SEGMENT;
FI;
CONFORMING-CODE-SEGMENT:
IF DPL > CPL THEN #GP(new code segment selector); FI;
IF segment not present THEN #NP(new code segment selector);
FI;
IF OperandSize 32
THEN
IF stack not large enough for a 6-byte return address THEN #SS(0); FI;
IF the instruction pointer is not within code segment limit THEN #GP(0);
FI;
Push(CS); (* padded with 16 high-order bits *)
Push(EIP);
CS DEST[NewCodeSegmentSelector);
(* segment descriptor information also loaded *)
CS(RPL) CPL
EIP DEST[offset);
ELSE (* OperandSize
16 *)
IF stack not large enough for a 4-byte return address THEN #SS(0); FI;
IF the instruction pointer is not within code segment limit THEN #GP(0);
FI;
Push(CS);
Push(IP);
CS DEST[NewCodeSegmentSelector);
(* segment descriptor information also loaded *)
CS(RPL) CPL
EIP DEST[offset)
AND 0000FFFFH; (* clear upper 16 bits *)
FI;
END;
NONCONFORMING-CODE-SEGMENT:
IF (RPL > CPL) OR (DPL CPL) THEN #GP(new code segment selector); FI;
IF segment not present THEN #NP(new code segment selector);
FI;
IF stack not large enough for return address THEN #SS(0); FI;
tempEIP DEST[offset)
IF OperandSize=16
THEN
tempEIP tempEIP AND
0000FFFFH; (* clear upper 16 bits *)
FI;
IF tempEIP outside code segment limit THEN #GP(0); FI;
IF OperandSize 32
THEN
Push(CS); (* padded with 16 high-order bits *)
Push(EIP);
CS DEST[NewCodeSegmentSelector);
(* segment descriptor information also loaded *)
CS(RPL) CPL;
EIP tempEIP;
ELSE (* OperandSize
16 *)
Push(CS);
Push(IP);
CS DEST[NewCodeSegmentSelector);
(* segment descriptor information also loaded *)
CS(RPL) CPL;
EIP tempEIP;
FI;
END;
CALL-GATE:
IF call gate DPL < CPL or RPL THEN #GP(call gate
selector); FI;
IF call gate not present THEN #NP(call gate selector);
FI;
IF call gate code-segment selector is null THEN #GP(0); FI;
IF call gate code-segment selector index is outside descriptor table limits
THEN #GP(code segment selector); FI;
Read code segment descriptor;
IF code-segment segment descriptor does not indicate a code segment
OR code-segment segment descriptor DPL > CPL
THEN #GP(code segment selector); FI;
IF code segment not present THEN #NP(new code segment
selector); FI;
IF code segment is non-conforming AND DPL < CPL
THEN go to MORE-PRIVILEGE;
ELSE go to SAME-PRIVILEGE;
FI;
END;
MORE-PRIVILEGE:
IF current TSS is 32-bit TSS
THEN
TSSstackAddress new
code segment (DPL * 8) + 4
IF (TSSstackAddress + 7) > TSS limit
THEN #TS(current TSS selector); FI;
newSS TSSstackAddress
+ 4;
newESP
stack address;
ELSE (* TSS is 16-bit *)
TSSstackAddress new
code segment (DPL * 4) + 2
IF (TSSstackAddress + 4) > TSS limit
THEN #TS(current TSS selector); FI;
newESP
TSSstackAddress;
newSS TSSstackAddress
+ 2;
FI;
IF stack segment selector is null THEN #TS(stack segment
selector); FI;
IF stack segment selector index is not within its descriptor table limits
THEN #TS(SS selector); FI
Read code segment descriptor;
IF stack segment selector's RPL DPL of code segment
OR stack segment DPL
DPL of code segment
OR stack segment is not a writable data segment
THEN #TS(SS selector); FI
IF stack segment not present THEN #SS(SS selector); FI;
IF CallGateSize 32
THEN
IF stack does not have room for parameters plus 16 bytes
THEN #SS(SS selector); FI;
IF CallGate(InstructionPointer) not within code segment
limit THEN #GP(0); FI;
SS newSS;
(* segment descriptor information also loaded *)
ESP newESP;
CS:EIP CallGate(CS:InstructionPointer);
(* segment descriptor information also loaded *)
Push(oldSS:oldESP); (* from calling procedure
*)
temp parameter
count from call gate, masked to 5 bits;
Push(parameters from calling procedure's stack, temp)
Push(oldCS:oldEIP); (* return address to calling
procedure *)
ELSE (* CallGateSize 16 *)
IF stack does not have room for parameters plus 8 bytes
THEN #SS(SS selector); FI;
IF (CallGate(InstructionPointer) AND FFFFH) not within
code segment limit
THEN #GP(0); FI;
SS newSS;
(* segment descriptor information also loaded *)
ESP newESP;
CS:IP CallGate(CS:InstructionPointer);
(* segment descriptor information also loaded *)
Push(oldSS:oldESP); (* from calling procedure *)
temp parameter
count from call gate, masked to 5 bits;
Push(parameters from calling procedure's stack, temp)
Push(oldCS:oldEIP); (* return address to calling procedure *)
FI;
CPL CodeSegment(DPL)
CS(RPL) CPL
END;
SAME-PRIVILEGE:
IF CallGateSize 32
THEN
IF stack does not have room for 8 bytes
THEN #SS(0); FI;
IF EIP not within code segment limit then #GP(0); FI;
CS:EIP CallGate(CS:EIP)
(* segment descriptor information also loaded *)
Push(oldCS:oldEIP); (* return address to calling procedure *)
ELSE (* CallGateSize
16 *)
IF stack does not have room for parameters plus 4 bytes
THEN #SS(0); FI;
IF IP not within code segment limit THEN #GP(0); FI;
CS:IP CallGate(CS:instruction
pointer)
(* segment descriptor information also loaded *)
Push(oldCS:oldIP); (* return address to calling procedure *)
FI;
CS(RPL) CPL
END;
TASK-GATE:
IF task gate DPL < CPL or RPL
THEN #GP(task gate selector);
FI;
IF task gate not present
THEN #NP(task gate selector);
FI;
Read the TSS segment selector in the task-gate descriptor;
IF TSS segment selector local/global bit is set to local
OR index not within GDT limits
THEN #GP(TSS selector);
FI;
Access TSS descriptor in GDT;
IF TSS descriptor specifies that the TSS is busy (low-order 5 bits set
to 00001)
THEN #GP(TSS selector);
FI;
IF TSS not present
THEN #NP(TSS selector);
FI;
SWITCH-TASKS (with nesting) to TSS;
IF EIP not within code segment limit
THEN #GP(0);
FI;
END;
TASK-STATE-SEGMENT:
IF TSS DPL < CPL or RPL
OR TSS descriptor indicates TSS not available
THEN #GP(TSS selector);
FI;
IF TSS is not present
THEN #NP(TSS selector);
FI;
SWITCH-TASKS (with nesting) to TSS
IF EIP not within code segment limit
THEN #GP(0);
FI;
END;
All flags are affected if a task switch occurs; no flags are affected if a task switch does not occur.
#GP(0) - If target offset in destination operand is beyond the new code segment limit. If the segment selector in the destination operand is null. If the code segment selector in the gate is null. If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit. If the DS, ES, FS, or GS register is used to access memory and it contains a null segment selector.
#GP(selector) - If code segment or gate or TSS selector index is outside descriptor table limits. If the segment descriptor pointed to by the segment selector in the destination operand is not for a conforming-code segment, nonconforming-code segment, call gate, task gate, or task state segment. If the DPL for a nonconforming-code segment is not equal to the CPL or the RPL for the segment's segment selector is greater than the CPL. If the DPL for a conforming-code segment is greater than the CPL. If the DPL from a call-gate, task-gate, or TSS segment descriptor is less than the CPL or than the RPL of the call-gate, task-gate, or TSS's segment selector. If the segment descriptor for a segment selector from a call gate does not indicate it is a code segment. If the segment selector from a call gate is beyond the descriptor table limits. If the DPL for a code-segment obtained from a call gate is greater than the CPL. If the segment selector for a TSS has its local/global bit set for local. If a TSS segment descriptor specifies that the TSS is busy or not available.
#SS(0) - If pushing the return address, parameters, or stack segment pointer onto the stack exceeds the bounds of the stack segment, when no stack switch occurs. If a memory operand effective address is outside the SS segment limit.
#SS(selector) - If pushing the return address, parameters, or stack segment pointer onto the stack exceeds the bounds of the stack segment, when a stack switch occurs. If the SS register is being loaded as part of a stack switch and the segment pointed to is marked not present. If stack segment does not have room for the return address, parameters, or stack segment pointer, when stack switch occurs.
#NP(selector) - If a code segment, data segment, stack segment, call gate, task gate, or TSS is not present.
#TS(selector) - If the new stack segment selector and ESP are beyond the end of the TSS. If the new stack segment selector is null. If the RPL of the new stack segment selector in the TSS is not equal to the DPL of the code segment being accessed. If DPL of the stack segment descriptor for the new stack segment is not equal to the DPL of the code segment descriptor. If the new stack segment is not a writable data segment. If segment-selector index for stack segment is outside descriptor table limits.
#PF(fault-code) - If a page fault occurs.
#AC(0) - If an unaligned memory access occurs when the CPL is 3 and alignment checking is enabled.
#GP - If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit. If the target offset is beyond the code segment limit.
#GP(0) - If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit. If the target offset is beyond the code segment limit.
#PF(fault-code) - If a page fault occurs.
#AC(0) - If an unaligned memory access occurs when alignment checking is enabled.
For details, see Volume 2A and Volume 2B of the Intel(R) 64 and IA-32 Intel Architecture Software Developer's Manual. For the latest updates on the instruction set information, go to the web site.