summaryrefslogtreecommitdiff
path: root/v4.0/src/DEV/XMAEM/INDEIDT.ASM
blob: 28e9161ec6f2d4f50804a7cb5adf5f3fe752cc12 (plain) (blame)
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
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
PAGE    60,132
TITLE   INDEIDT - 386 XMA Emulator - Build Interrupt Descriptor Table

COMMENT #
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*                                                                             *
* MODULE NAME     : INDEIDT                                                   *
*                                                                             *
*                                                                             *
*                    5669-196 (C) COPYRIGHT 1988 Microsoft Corp.              *
*	                                                                      *
* DESCRIPTIVE NAME: Build the Interrupt Descriptor Table (IDT)                *
*                                                                             *
* STATUS (LEVEL)  : Version (0) Level (2.0)                                   *
*                                                                             *
* FUNCTION        : Build the Interrupt Descriptor Table for the 80386 XMA    *
*                   emulator.                                                 *
*                                                                             *
* MODULE TYPE     : ASM                                                       *
*                                                                             *
* REGISTER USAGE  : 80386 Standard                                            *
*                                                                             *
* RESTRICTIONS    : None                                                      *
*                                                                             *
* DEPENDENCIES    : None                                                      *
*                                                                             *
* ENTRY POINT     : SIDT_BLD (not to be confused with SIDTBLD)                *
*                                                                             *
* LINKAGE         : Called by INDEINI                                         *
*                                                                             *
* INPUT PARMS     : None                                                      *
*                                                                             *
* RETURN PARMS    : None                                                      *
*                                                                             *
* OTHER EFFECTS   : None                                                      *
*                                                                             *
* EXIT NORMAL     : Return to INDEINI                                         *
*                                                                             *
* EXIT ERROR      : None                                                      *
*                                                                             *
* EXTERNAL                                                                    *
* REFERENCES      : VEXCP13 - Entry point for INDEEXC                         *
*                                                                             *
* SUB-ROUTINES    : BLD_IDT - Put the entries into the IDT                    *
*                                                                             *
* MACROS          : DATAOV - Create a prefix for the following instruction    *
*                            so that it accesses data 32 bits wide            *
*                   ADDROV - Create a prefix for the following instruction    *
*                            so that it uses addresses that are 32 bits wide  *
*                                                                             *
* CONTROL BLOCKS  : INDEDAT                                                   *
*                                                                             *
* CHANGE ACTIVITY :                                                           *
*                                                                             *
* $MOD(INDEIDT) COMP(LOAD) PROD(3270PC) :                                     *
*                                                                             *
* $D0=D0004700 410 870530 D : NEW FOR RELEASE 1.1                             *
* $P1=P0000312 410 870803 D : CHANGE COMPONENT FROM MISC TO LOAD              *
* $P2=P0000xxx 120 880517 D : HANDLE INT 0D FROM V86 TASK, I.E., OPTICAL DISK *
*                                                                             *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
#

        .286P                 ; Enable recognition of 286 privileged instructs.

        .XLIST                ; Turn off the listing
        INCLUDE INDEDAT.INC   ; System data structures and equates

        IF1                   ; Only include macros on the first pass
        INCLUDE INDEOVP.MAC
        ENDIF
        .LIST                 ; Turn on the listing
PAGE

PROG    SEGMENT PARA    PUBLIC  'PROG'

        ASSUME  CS:PROG
        ASSUME  SS:NOTHING
        ASSUME  DS:NOTHING
        ASSUME  ES:NOTHING

INDEIDT LABEL   NEAR

; Let these entry points be known to other modules.

        PUBLIC  INDEIDT
        PUBLIC  SIDT_BLD

; This is the entry point to INDEEXC.

        EXTRN   VEXCPT13:NEAR

PAGE
; Define the stack structure for our fast path.  For all the interrupts that we
; don't want to handle we just pass the interrupt back to the real interrupt
; vector.  The entry points for these vectors push the interrupt vector offset
; (interrupt number * 4) onto the stack and then call FASTPATH to pass the
; interrupt to the real vector.  FASTPATH pushes BP, AX, DI and SI on to the
; stack.  The following structure is a map of the stack after these registers
; are pushed.  This structure allows us to access info on the stack.

SPSTACK STRUC

SP_SI   DW      0             ; Saved ESI (32 bit SI)
        DW      0
SP_DI   DW      0             ; Saved EDI (32 bit DI)
        DW      0
SP_AX   DW      0             ; Saved EAX
        DW      0
SP_BP   DW      0             ; Saved BP (only 16 bits)
SP_EX   DW      0             ; Interrupt vector offset (interrupt number * 4)

; The following information is saved by the 80386

SP_IP   DW      0             ; Interruptee's EIP (32 bit IP)
SP_IP2  DW      0
SP_CS   DW      0             ; Interruptee's CS (16 bit CS and 16 bit junk)
SP_CS2  DW      0
SP_FL   DW      0             ; Interruptee's Eflags (32 bit flags)
SP_FL2  DW      0
SP_SP   DW      0             ; Interruptee's ESP
SP_SP2  DW      0
SP_SS   DW      0             ; Interruptee's SS
SP_SS2  DW      0
SP_VMES DW      0             ; Interruptee's ES
        DW      0
SP_VMDS DW      0             ; Interruptee's DS
        DW      0
SP_VMFS DW      0             ; Interruptee's FS
        DW      0
SP_VMGS DW      0             ; Interruptee's GS
        DW      0
SP_STK  DW      0             ; The rest of the stack

SPSTACK ENDS

SP_START EQU    0             ; Offset from BP of the start of the save area
                              ; BP is set ot point to the start of the save area

PAGE

SIDTBLD         PROC    NEAR

; Generate the entry points for all (yes, ALL) 256 interrupt vectors.  For
; interrupt 0D (general Protection exception) we will check if it was the V86
; task that faulted.  If so, then we will just pass the interrupt back to the
; V86 task.  Else, we will go to our exception handler since the interrupt
; happened because of the emulator.
;
; For interrupts 00, 01, 02, 03, 04, 05, 06, 07, 09, 0A, 0B, 0C, 0E and 15 we
; will go to our exception handler.
;
; For all other interrupts we will go to the FASTPATH routine which will pass
; the interrupt back to the V86 interrupt vector.
;
; Note: For interrupts that go to our exception handler we push a 32 bit error
;       code and then push the interrupt number.  For the FASTPATH interrupts
;       we push the interrupt vector offset (interrupt number *4).  This results
;       in different stack structures depending on how the interrupt is handled.
;       So be careful when you're trying to figure out what's on the stack.
;

; Interrupt 0D

                IRP     V,<0D>
VEC&V:
                PUSH    0&V&H           ; Push the interrupt number (0D)
                PUSH    BP              ; Save BP
                DATAOV                  ;                                   @P2A
                PUSH    AX              ; Save EAX, all 32bits of it.       @P2A
                DATAOV                  ;                                   @P2A
                PUSH    DI              ; Save EDI                          @P2A
                DATAOV                  ;                                   @P2A
                PUSH    SI              ; Save ESI                          @P2A
                MOV     BP,SP           ; Point BP to the save area         @P2A

                ; Now we must check if the INT 0D came from the V86 task     P2A
                ; or if it was a General Protection exception.  In the       P2A
                ; case of a General Protection exception the 80386 puts      P2A
                ; an error code on the stack after pushing the EFLAGS, CS    P2A
                ; and EIP.  The error code is 32 bits wide.  If the V86      P2A
                ; task issues an INT 0D, an error code is NOT placed on      P2A
                ; the stack.  In this case we want to pass the interrupt     P2A
                ; back to the V86 task instead of going to our exception     P2A
                ; handler.  The way we check for an error code is by         P2A
                ; checking how much ESP has been decremented since the       P2A
                ; start of the interrupt.  The original ESP is saved in      P2A
                ; the TSS.  Our stack definition above does not include      P2A
                ; an error code.  So if ESP has been decremented more than   P2A
                ; the size of our structure, we can know that an error       P2A
                ; code is on the stack and then go to our exception          P2A
                ; handler.                                                   P2A

                MOV     AX,SCRUBBER.TSS_PTR ; Load DS with the selector     @P2A
                MOV     DS,AX           ;   that accesses the TSS as data   @P2A
                MOV     SI,0            ; Base for reading the TSS          @P2A
                DATAOV                  ;                                   @P2A
                MOV     AX,[SI].ETSS_SP0 ; Get the original SP before the   @P2A
                DATAOV                  ;   interrupt                       @P2A
                SUB     AX,SP           ; Subtract the current stack        @P2A
                                        ;   pointer                         @P2A
                CMP     AX,SP_STK       ; Check for an error code           @P2A
                                        ;                                   @P2D
                JG      SKIP&V          ; If there's an error code, go      @P2C
                                        ; handle the exception               P2C
                MOV     WORD PTR [BP+SP_EX],0&V&H*4 ; If there is no error  @P2A
                                        ; code then multiply the vector      P2A
                                        ; number by four for the FASTPATH    P2A
                                        ; code.                              P2A
                JMP     PASS_ON         ; Give the interrupt back to the    @P2C
                                        ;   V86 task.
SKIP&V:         DATAOV                  ;                                   @P2A
                POP     SI              ; Restore ESI from off our stack    @P2A
                DATAOV                  ;                                   @P2A
                POP     DI              ; Restore EDI                       @P2A
                DATAOV                  ;                                   @P2A
                POP     AX              ; Restore EAX                       @P2A
                POP     BP              ; Take BP off the stack.  This leaves
                                        ;   the interrupt number that we pushed
                                        ;   above and the error code that was
                                        ;   pushed by the 386 on the INT 0D.
                JMP     VEXCPT13        ; Go to the exception handler.

                ENDM

PAGE
; For interrupts 00, 01, 02, 03, 04, 05, 06, 07, 09, 0A, 0B, 0C, 0E and 15
; push a dummy error code of 0 and then the interrupt number.  Then go to the
; exception handler.

                IRP     V,<00,01,02,03,04,05,06,07,09,0A,0B,0C,0E,15>
VEC&V:
                PUSH    0               ; Push a dummy error code of 0
                PUSH    0               ; 32 bits wide
SKIP&V:
                PUSH    0&V&H           ; Push the interrupt number
                JMP     VEXCPT13        ; Go to the exception handler
                ENDM

PAGE
; For the rest of the interrupts push the interrupt vector offset (interrupt
; number * 4) and go to the fast path routine.
;
; INT 08H is given the FASTPATH.  It's the double fault interrupt so we are
; dead any way.  This interrupt is normally used for the timer interrupt.
;
; INT 10H, BIOS video calls, is given the fastest code path by putting it just
; before the FASTPATH routine.

                IRP     V,<08,0F,11,12,13,14,16,17,18,19,1A,1B,1C,1D,1E,1F>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<20,21,22,23,24,25,26,27,28,29,2A,2B,2C,2D,2E,2F>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<30,31,32,33,34,35,36,37,38,39,3A,3B,3C,3D,3E,3F>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<40,41,42,43,44,45,46,47,48,49,4A,4B,4C,4D,4E,4F>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<50,51,52,53,54,55,56,57,58,59,5A,5B,5C,5D,5E,5F>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<60,61,62,63,64,65,66,67,68,69,6A,6B,6C,6D,6E,6F>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<70,71,72,73,74,75,76,77,78,79,7A,7B,7C,7D,7E,7F>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<80,81,82,83,84,85,86,87,88,89,8A,8B,8C,8D,8E,8F>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<90,91,92,93,94,95,96,97,98,99,9A,9B,9C,9D,9E,9F>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,BA,BB,BC,BD,BE,BF>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,CA,CB,CC,CD,CE,CF>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<E0,E1,E2,E3,E4,E5,E6,E7,E8,E9,EA,EB,EC,ED,EE,EF>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM
                IRP     V,<F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,FA,FB,FC,FD,FE,FF>
VEC&V:
                PUSH    0&V&H*4         ; Push the interrupt vector offset
                JMP     FASTPATH        ; Go to the fastpath routine
                ENDM

VEC10:
                PUSH    010H*4          ; Push the interrupt vector offset

PAGE
FASTPATH:
        PUSH    BP                      ; Save BP
        DATAOV
        PUSH    AX                      ; Save EAX, all 32bits of it.
        DATAOV
        PUSH    DI                      ; Save EDI
        DATAOV
        PUSH    SI                      ; Save ESI
        MOV     BP,SP                   ; Point BP to the save area

PASS_ON:                                ;                                  @P2C
        CLD                             ; All string operations go forward

        MOV     AX,HUGE_PTR             ; Load DS and ES with a selector that
        MOV     DS,AX                   ;   accesses all of memory as data
        MOV     ES,AX
        DATAOV
        SUB     DI,DI                   ; Clear EDI
        MOV     DI,SS:[BP+SP_SP]        ; Load DI with the interruptee's SP
        SUB     DI,6                    ; Decrement "SP" to simulate the pushing
                                        ;   of the flags, CS and IP on an INT.
        MOV     SS:WORD PTR [BP+SP_SP],DI ; Replace the user's SP

        DATAOV
        SUB     AX,AX                   ; Clear EAX
        MOV     AX,SS:[BP+SP_SS]        ; Load AX with the user's SS register
        DATAOV                          ; Shift "SS" left four bits to convert
        SHL     AX,4                    ;   it to an offset
        DATAOV                          ; Add on "SP" to get a 32 bit offset
        ADD     DI,AX                   ;   from 0 of the user's stack.

; Put the user's IP, CS and flags onto his stack.  This is done in reverse
; order because we are moving forward in memory whereas stacks grow backward.

        MOV     AX,SS:[BP+SP_IP]        ; Get the user's IP
        ADDROV
        STOSW                           ; And put it on the stack
        ADDROV                          ; Intel bug # A0-119
        NOP                             ; Intel bug # A0-119

        MOV     AX,SS:[BP+SP_CS]        ; Get the user's CS
        ADDROV
        STOSW                           ; And put it on the stack
        ADDROV                          ; Intel bug # A0-119
        NOP                             ; Intel bug # A0-119

        MOV     AX,SS:[BP+SP_FL]        ; Get the user's flags
        ADDROV
        STOSW                           ; And put them on the stack
        ADDROV                          ; Intel bug # A0-119
        NOP                             ; Intel bug # A0-119

        AND     AX,3CFFH                ; Clean up the flags for our IRET by
        MOV     WORD PTR SS:[BP+SP_FL],AX  ; setting IOPL to 3

; Replace the interruptee's CS:IP with the CS:IP of the interrupt vector.  When
; we IRET back to the V86 task control will go to the interrupt routine.

        MOV     SI,SS:[BP+SP_EX]        ; Get the interrupt vector offset
        LODSW                           ; Get the IP of the interrupt vector
        MOV     WORD PTR SS:[BP+SP_IP],AX ; Replace the user's IP
        LODSW                           ; Get the CS of the interrupt vector
        MOV     WORD PTR SS:[BP+SP_CS],AX ; Replace the user's CS

        DATAOV
        POP     SI                      ; Restore ESI from off our stack
        DATAOV
        POP     DI                      ; Restore EDI
        DATAOV
        POP     AX                      ; Restore EAX
        POP     BP                      ; Restore BP
        ADD     SP,(SP_IP-SP_EX)        ; Step SP past the interrupt vector
                                        ;   offset
        DATAOV
        IRET                            ; Give control back to the interruptee

PAGE

; Build a talbe of the offsets of all the interrupt entry points.  This table
; is used as input to the procedure that builds the IDT.

SIDT_OFFSETS            LABEL   WORD

                IRP     V,<00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<20,21,22,23,24,25,26,27,28,29,2A,2B,2C,2D,2E,2F>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<30,31,32,33,34,35,36,37,38,39,3A,3B,3C,3D,3E,3F>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<40,41,42,43,44,45,46,47,48,49,4A,4B,4C,4D,4E,4F>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<50,51,52,53,54,55,56,57,58,59,5A,5B,5C,5D,5E,5F>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<60,61,62,63,64,65,66,67,68,69,6A,6B,6C,6D,6E,6F>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<70,71,72,73,74,75,76,77,78,79,7A,7B,7C,7D,7E,7F>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<80,81,82,83,84,85,86,87,88,89,8A,8B,8C,8D,8E,8F>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<90,91,92,93,94,95,96,97,98,99,9A,9B,9C,9D,9E,9F>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,BA,BB,BC,BD,BE,BF>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,CA,CB,CC,CD,CE,CF>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<E0,E1,E2,E3,E4,E5,E6,E7,E8,E9,EA,EB,EC,ED,EE,EF>
                DW      OFFSET VEC&V
                ENDM
                IRP     V,<F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,FA,FB,FC,FD,FE,FF>
                DW      OFFSET VEC&V
                ENDM
PAGE
SIDT_BLD:

; Build the system IDT.  The system IDT will contain 256 interrupt gates.

        MOV     AX,CS                   ; Set DS:SI to point to the table of
        MOV     DS,AX                   ;   interrupt entry points
        MOV     SI,OFFSET SIDT_OFFSETS

        MOV     DI,SIDT_LOC             ; Set ES:DI to point to the beginning
                                        ;   of the IDT
        MOV     BX,SYS_PATCH_CS         ; Load BX with the selector for the
                                        ;   segment of the interrupt routines.
                                        ;   It's our code segment.

;       DX contains the second highest word of the interrupt descriptor.

        MOV     DH,0EEH                 ; Set DPL to 3 to reduce the number of
                                        ;   exceptions
        MOV     DL,0                    ; The word count field is unused

        MOV     CX,256                  ; 256 interrupt gates

        CALL    BLD_IDT                 ; Go build the IDT

        RET                             ; Return to INDEINI

PAGE

; This loop builds descriptors in the IDT.  DS:SI points to a table of 16 bit
; offsets for the interrupt entry points.  ES:DI points to the start of the IDT.
; BX contains the segment selector of the interrupt entry points.  DX contains
; the DPL of the interrupt gates.

BLD_IDT:
        MOVSW                         ; Get an interrupt routine entry point
                                      ;   and put it in the offset field
        MOV     AX,BX                 ; Get the segment selector
        STOSW                         ;   and put it in the selector field
        MOV     AX,DX                 ; Get the interrupt gate DPL
        STOSW                         ;   and put it in the access rights field
        MOV     AX,0                  ; Zero out the reserved portions
        STOSW
        LOOP    BLD_IDT               ; Repeat for all interrupt vectors

        RET

SIDTBLD ENDP

PROG    ENDS

        END