forked from NJU-ProjectN/i386-manual
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CALL.htm
382 lines (341 loc) · 14 KB
/
CALL.htm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML>
<HEAD>
<TITLE>80386 Programmer's Reference Manual -- Opcode CALL</TITLE>
</HEAD>
<BODY STYLE="width:80ch">
<B>up:</B> <A HREF="c17.htm">
Chapter 17 -- 80386 Instruction Set</A><BR>
<B>prev:</B><A HREF="BTS.htm"> BTS Bit Test and Set</A><BR>
<B>next:</B><A HREF="CBW.htm"> CBW/CWDE Convert Byte to Word/Convert Word to Doubleword</A>
<P>
<HR>
<P>
<H1>CALL -- Call Procedure</H1>
<PRE>
Opcode Instruction Clocks
Values of ts are given by the following table:
New Task
386 TSS 386 TSS 286 TSS
Old VM = 0 VM = 1
Task Via Task Gate?
N Y N Y N Y
386 300 309 217 226 273 282
TSS VM=0
286 298 307 217 226 273 282
TSS Description
E8 cw CALL rel16 7+m Call near, displacement relative
to next instruction
FF /2 CALL r/m16 7+m/10+m Call near, register
indirect/memory indirect
9A cd CALL ptr16:16 17+m,pm=34+m Call intersegment, to full
pointer given
9A cd CALL ptr16:16 pm=52+m Call gate, same privilege
9A cd CALL ptr16:16 pm=86+m Call gate, more privilege, no
parameters
9A cd CALL ptr16:16 pm=94+4x+m Call gate, more privilege, x
parameters
9A cd CALL ptr16:16 ts Call to task
FF /3 CALL m16:16 22+m,pm=38+m Call intersegment, address at
r/m dword
FF /3 CALL m16:16 pm=56+m Call gate, same privilege
FF /3 CALL m16:16 pm=90+m Call gate, more privilege, no
parameters
FF /3 CALL m16:16 pm=98+4x+m Call gate, more privilege, x
parameters
FF /3 CALL m16:16 5 + ts Call to task
E8 cd CALL rel32 7+m Call near, displacement relative
to next instruction
FF /2 CALL r/m32 7+m/10+m Call near, indirect
9A cp CALL ptr16:32 17+m,pm=34+m Call intersegment, to full
pointer given
9A cp CALL ptr16:32 pm=52+m Call gate, same privilege
9A cp CALL ptr16:32 pm=86+m Call gate, more privilege, no
parameters
9A cp CALL ptr32:32 pm=94+4x+m Call gate, more privilege, x
parameters
9A cp CALL ptr16:32 ts Call to task
FF /3 CALL m16:32 22+m,pm=38+m Call intersegment, address at
r/m dword
FF /3 CALL m16:32 pm=56+m Call gate, same privilege
FF /3 CALL m16:32 pm=90+m Call gate, more privilege, no
parameters
FF /3 CALL m16:32 pm=98+4x+m Call gate, more privilege, x
parameters
FF /3 CALL m16:32 5 + ts Call to task
</PRE>
<EM>
<H3>Note</H3>
Values of ts are given by the following table:
<PRE>
New Task
386 TSS 386 TSS 286 TSS
Old VM = 0 VM = 1
Task Via Task Gate?
N Y N Y N Y
386 300 309 217 226 273 282
TSS VM=0
286 298 307 217 226 273 282
TSS
</PRE>
</EM>
<H2>Operation</H2>
<PRE>
IF rel16 or rel32 type of call
THEN (* near relative call *)
IF OperandSize = 16
THEN
Push(IP);
EIP := (EIP + rel16) AND 0000FFFFH;
ELSE (* OperandSize = 32 *)
Push(EIP);
EIP := EIP + rel32;
FI;
FI;
IF r/m16 or r/m32 type of call
THEN (* near absolute call *)
IF OperandSize = 16
THEN
Push(IP);
EIP := [r/m16] AND 0000FFFFH;
ELSE (* OperandSize = 32 *)
Push(EIP);
EIP := [r/m32];
FI;
FI;
IF (PE = 0 OR (PE = 1 AND VM = 1))
(* real mode or virtual 8086 mode *)
AND instruction = far CALL
(* i.e., operand type is m16:16, m16:32, ptr16:16, ptr16:32 *)
THEN
IF OperandSize = 16
THEN
Push(CS);
Push(IP); (* address of next instruction; 16 bits *)
ELSE
Push(CS); (* padded with 16 high-order bits *)
Push(EIP); (* address of next instruction; 32 bits *)
FI;
IF operand type is m16:16 or m16:32
THEN (* indirect far call *)
IF OperandSize = 16
THEN
CS:IP := [m16:16];
EIP := EIP AND 0000FFFFH; (* clear upper 16 bits *)
ELSE (* OperandSize = 32 *)
CS:EIP := [m16:32];
FI;
FI;
IF operand type is ptr16:16 or ptr16:32
THEN (* direct far call *)
IF OperandSize = 16
THEN
CS:IP := ptr16:16;
EIP := EIP AND 0000FFFFH; (* clear upper 16 bits *)
ELSE (* OperandSize = 32 *)
CS:EIP := ptr16:32;
FI;
FI;
FI;
IF (PE = 1 AND VM = 0) (* Protected mode, not V86 mode *)
AND instruction = far CALL
THEN
If indirect, then check access of EA doubleword;
#GP(0) if limit violation;
New CS selector must not be null else #GP(0);
Check that new CS selector index is within its
descriptor table limits; else #GP(new CS selector);
Examine AR byte of selected descriptor for various legal values;
depending on value:
go to CONFORMING-CODE-SEGMENT;
go to NONCONFORMING-CODE-SEGMENT;
go to CALL-GATE;
go to TASK-GATE;
go to TASK-STATE-SEGMENT;
ELSE #GP(code segment selector);
FI;
CONFORMING-CODE-SEGMENT:
DPL must be <= CPL ELSE #GP(code segment selector);
Segment must be present ELSE #NP(code segment selector);
Stack must be big enough for return address ELSE #SS(0);
Instruction pointer must be in code segment limit ELSE #GP(0);
Load code segment descriptor into CS register;
Load CS with new code segment selector;
Load EIP with zero-extend(new offset);
IF OperandSize=16 THEN EIP := EIP AND 0000FFFFH; FI;
NONCONFORMING-CODE-SEGMENT:
RPL must be <= CPL ELSE #GP(code segment selector)
DPL must be = CPL ELSE #GP(code segment selector)
Segment must be present ELSE #NP(code segment selector)
Stack must be big enough for return address ELSE #SS(0)
Instruction pointer must be in code segment limit ELSE #GP(0)
Load code segment descriptor into CS register
Load CS with new code segment selector
Set RPL of CS to CPL
Load EIP with zero-extend(new offset);
IF OperandSize=16 THEN EIP := EIP AND 0000FFFFH; FI;
CALL-GATE:
Call gate DPL must be >= CPL ELSE #GP(call gate selector)
Call gate DPL must be >= RPL ELSE #GP(call gate selector)
Call gate must be present ELSE #NP(call gate selector)
Examine code segment selector in call gate descriptor:
Selector must not be null ELSE #GP(0)
Selector must be within its descriptor table
limits ELSE #GP(code segment selector)
AR byte of selected descriptor must indicate code
segment ELSE #GP(code segment selector)
DPL of selected descriptor must be <= CPL ELSE
#GP(code segment selector)
IF non-conforming code segment AND DPL < CPL
THEN go to MORE-PRIVILEGE
ELSE go to SAME-PRIVILEGE
FI;
MORE-PRIVILEGE:
Get new SS selector for new privilege level from TSS
Check selector and descriptor for new SS:
Selector must not be null ELSE #TS(0)
Selector index must be within its descriptor
table limits ELSE #TS(SS selector)
Selector's RPL must equal DPL of code segment
ELSE #TS(SS selector)
Stack segment DPL must equal DPL of code
segment ELSE #TS(SS selector)
Descriptor must indicate writable data segment
ELSE #TS(SS selector)
Segment present ELSE #SS(SS selector)
IF OperandSize=32
THEN
New stack must have room for parameters plus 16 bytes
ELSE #SS(0)
EIP must be in code segment limit ELSE #GP(0)
Load new SS:eSP value from TSS
Load new CS:EIP value from gate
ELSE
New stack must have room for parameters plus 8 bytes ELSE #SS(0)
IP must be in code segment limit ELSE #GP(0)
Load new SS:eSP value from TSS
Load new CS:IP value from gate
FI;
Load CS descriptor
Load SS descriptor
Push long pointer of old stack onto new stack
Get word count from call gate, mask to 5 bits
Copy parameters from old stack onto new stack
Push return address onto new stack
Set CPL to stack segment DPL
Set RPL of CS to CPL
SAME-PRIVILEGE:
IF OperandSize=32
THEN
Stack must have room for 6-byte return address (padded to 8 bytes)
ELSE #SS(0)
EIP must be within code segment limit ELSE #GP(0)
Load CS:EIP from gate
ELSE
Stack must have room for 4-byte return address ELSE #SS(0)
IP must be within code segment limit ELSE #GP(0)
Load CS:IP from gate
FI;
Push return address onto stack
Load code segment descriptor into CS register
Set RPL of CS to CPL
TASK-GATE:
Task gate DPL must be >= CPL ELSE #TS(gate selector)
Task gate DPL must be >= RPL ELSE #TS(gate selector)
Task Gate must be present ELSE #NP(gate selector)
Examine selector to TSS, given in Task Gate descriptor:
Must specify global in the local/global bit ELSE #TS(TSS selector)
Index must be within GDT limits ELSE #TS(TSS selector)
TSS descriptor AR byte must specify nonbusy TSS
ELSE #TS(TSS selector)
Task State Segment must be present ELSE #NP(TSS selector)
SWITCH-TASKS (with nesting) to TSS
IP must be in code segment limit ELSE #TS(0)
TASK-STATE-SEGMENT:
TSS DPL must be >= CPL else #TS(TSS selector)
TSS DPL must be >= RPL ELSE #TS(TSS selector)
TSS descriptor AR byte must specify available TSS
ELSE #TS(TSS selector)
Task State Segment must be present ELSE #NP(TSS selector)
SWITCH-TASKS (with nesting) to TSS
IP must be in code segment limit ELSE #TS(0)
</PRE>
<H2>Description</H2>
The CALL instruction causes the procedure named in the operand to be
executed. When the procedure is complete (a return instruction is executed
within the procedure), execution continues at the instruction that follows
the CALL instruction.
<P>
The action of the different forms of the instruction are described below.
<P>
<STRONG>Near calls</STRONG>
are those with destinations of type r/m16, r/m32, rel16, rel32;
changing or saving the segment register value is not necessary. The CALL
rel16 and CALL rel32 forms add a signed offset to the address of the
instruction following CALL to determine the destination. The rel16 form is
used when the instruction's operand-size attribute is 16 bits; rel32 is used
when the operand-size attribute is 32 bits. The result is stored in the
32-bit EIP register. With rel16, the upper 16 bits of EIP are cleared,
resulting in an offset whose value does not exceed 16 bits. CALL r/m16 and
CALL r/m32 specify a register or memory location from which the absolute
segment offset is fetched. The offset fetched from r/m is 32 bits for an
operand-size attribute of 32 (r/m32), or 16 bits for an operand-size of 16
(r/m16). The offset of the instruction following CALL is pushed onto the
stack. It will be popped by a near
<A HREF="RET.htm">RET</A> instruction within the procedure. The
CS register is not changed by this form of CALL.
<P>
The <STRONG>far calls</STRONG>,
CALL ptr16:16 and CALL ptr16:32, use a four-byte or six-byte
operand as a long pointer to the procedure called. The CALL m16:16 and
m16:32 forms fetch the long pointer from the memory location
specified (indirection). In Real Address Mode or Virtual 8086 Mode, the long
pointer provides 16 bits for the CS register and 16 or 32 bits for the EIP
register (depending on the operand-size attribute). These forms of the
instruction push both CS and IP or EIP as a return address.
<P>
In Protected Mode, both long pointer forms consult the AR byte in the
descriptor indexed by the selector part of the long pointer. Depending on
the value of the AR byte, the call will perform one of the following types
of control transfers:
<UL>
<LI> A far call to the same protection level
<LI> An inter-protection level far call
<LI> A task switch
</UL>
For more information on Protected Mode control transfers, refer to
<A HREF="c06.htm">Chapter 6</A> and <A HREF="c07.htm">Chapter 7</A>.
<H2>Flags Affected</H2>
All flags are affected if a task switch occurs; no flags are affected if a
task switch does not occur
<H2>Protected Mode Exceptions</H2>
For <STRONG>far calls</STRONG>:
#GP, #NP, #SS, and #TS, as indicated in the list above
<P>
For <STRONG>near direct calls</STRONG>:
#GP(0) if procedure location is beyond the code
segment limits; #SS(0) if pushing the return address exceeds the bounds of
the stack segment; #PF (fault-code) for a page fault
For a <STRONG>near indirect call</STRONG>:
#GP(0) for an illegal memory operand effective
address in the CS, DS, ES, FS, or GS segments; #SS(0) for an illegal address
in the SS segment; #GP(0) if the indirect offset obtained is beyond the code
segment limits; #PF(fault-code) for a page fault
<H2>Real Address Mode Exceptions</H2>
Interrupt 13 if any part of the operand would lie outside of the effective
address space from 0 to 0FFFFH
<H2>Virtual 8086 Mode Exceptions</H2>
Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault
<H2>Notes</H2>
Any far call from a 32-bit code segment to 16-bit code segments should be
made from the first 64K bytes of the 32-bit code segment, since the
operand-size attribute of the instruction is set to 16, thus allowing only a
16-bit return address offset to be saved.
<P>
<HR>
<P>
<B>up:</B> <A HREF="c17.htm">
Chapter 17 -- 80386 Instruction Set</A><BR>
<B>prev:</B><A HREF="BTS.htm"> BTS Bit Test and Set</A><BR>
<B>next:</B><A HREF="CBW.htm"> CBW/CWDE Convert Byte to Word/Convert Word to Doubleword</A>
</BODY>