home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1990
/
06
/
schulman.lst
< prev
next >
Wrap
File List
|
1990-05-02
|
11KB
|
393 lines
_EXAMINING INSTANT-C_
by Andrew Schulman
[LISTING ONE]
; protmode.asm -- 286 protected-mode instructions
; requires MASM 5.0 or higher or TASM
; masm -ml protmode;
; or, tasm -ml protmode;
dosseg
.286p
.model large
.code
public _lsl, _lar, _verr, _verw, _sgdt, _sidt, _sldt
; extern unsigned far lsl(unsigned short sel);
; input: selector
; output: if valid and visible at current protection level,
; return segment limit (which is 0 for 1-byte seg!)
; else
; return 0
;
_lsl proc
enter 0, 0
sub ax, ax
lsl ax, [bp+6]
leave
ret
_lsl endp
; extern unsigned short far lar(unsigned short sel);
; input: selector
; output: if valid and visible at current protection level,
; return access rights (which will never be 0)
; else
; return 0
;
_lar proc
enter 0, 0
sub ax, ax
lar ax, [bp+6]
shr ax, 8
leave
ret
_lar endp
; extern BOOL far verr(unsigned short sel);
; input: selector
; output: valid for reading ? 1 : 0
;
_verr proc
enter 0, 0
mov ax, 1
verr word ptr [bp+6]
je short verr_okay
dec ax
verr_okay:
leave
ret
_verr endp
; extern BOOL far verw(unsigned short sel);
; input: selector
; output: valid for writing ? 1 : 0
;
_verw proc
enter 0, 0
mov ax, 1
verw word ptr [bp+6]
je short verw_okay
dec ax
verw_okay:
leave
ret
_verw endp
; extern void far sgdt(void far *gdt);
; input: far ptr to 6-byte structure
; output: fills structure with GDTR
;
_sgdt proc
enter 0, 0
les bx, dword ptr [bp+6]
sgdt fword ptr es:[bx]
leave
ret
_sgdt endp
; extern void far sidt(void far *idt);
; input: far ptr to 6-byte structure
; output: fills structure with IDTR
;
_sidt proc
enter 0, 0
les bx, dword ptr [bp+6]
sidt fword ptr es:[bx]
leave
ret
_sidt endp
;
; extern unsigned short sldt(void);
; input: none
; output: Local Descriptor Table register (LDTR)
;
_sldt proc
sldt ax
ret
_sldt endp
end
[LISTING TWO]
/* PROTMODE.H */
typedef enum { FALSE, TRUE } BOOL;
#ifdef InstantC
unsigned far lsl(unsigned short sel) {extern;}
unsigned short far lar(unsigned short sel) {extern;}
BOOL far verr(unsigned short sel) {extern;}
BOOL far verw(unsigned short sel) {extern;}
void far sgdt(void far *gdt) {extern;}
void far sidt(void far *idt) {extern;}
unsigned short sldt(void) {extern;}
#else
extern unsigned far lsl(unsigned short sel);
extern unsigned short far lar(unsigned short sel);
extern BOOL far verr(unsigned short sel);
extern BOOL far verw(unsigned short sel);
extern void far sgdt(void far *gdt);
extern void far sidt(void far *idt);
extern unsigned short sldt(void);
#endif
[LISTING THREE]
/* BROWSE.C */
#ifdef InstantC
#loadobj "protmode.obj"
#endif
#include "protmode.h"
void browse()
{
unsigned long addr;
unsigned i, acc;
for (i=0; i<0xFFFF; i++) // for all possible selectors
if (acc = lar(i)) // if a valid selector
{
addr = D16AbsAddress(MK_FP(i,0));
printf("%04X %06lX LAR=%02X LSL=%04X PL=%02X %s %s %s %s\n",
i, // selector
addr, // physical base addr
acc, // access-rights byte
lsl(i), // segment limit
i & 3, // protection level
verr(i) ? "VERR" : " ", // readable?
verw(i) ? "VERW" : " ", // writeable?
i & 4 ? "LDT" : "GDT", // which table?
i == addr >> 4 ? "TRANS" : ""); // transparent?
}
}
[LISTING FOUR]
/* SEL.C */
void sel(void far *fp)
{
extern DESCRIPTOR far *gdt;
extern DESCRIPTOR far *ldt;
unsigned seg = FP_SEG(fp);
unsigned index = seg >> 3;
DESCRIPTOR far *dt = (seg & 4) ? gdt : ldt; // table indicator
ACCESS_RIGHTS *pacc = (ACCESS_RIGHTS *) &dt[index].access;
printf("SEL=%04X ADDR=%02X%04X LIMIT=%04X ACCESS=%d%c%c%c%c%c%c\n",
seg, dt[index].addr_hi, dt[index].addr_lo, dt[index].limit,
// display access rights as if they were file attributes:
pacc->dpl,
pacc->accessed ? 'a' : '-',
pacc->read_write ? ((pacc->code_data) ? 'r' : 'w') : '-',
pacc->conf_exp ? ((pacc->code_data) ? 'f' : 'e') : '-',
pacc->code_data ? 'c' : 'd',
pacc->xsystem ? '-' : 's',
pacc->present ? 'p' : '-');
}
[FIGURE 1]
# char *p;
# #include <malloc.h>
MALLOC.H included
# p = malloc(10240)
address 03B8:01A6: ""
# #include "dos16.h"
DOS16.H included
# D16AbsAddress(p)
2940246 (0x2CDD56)
# #include <dos.h>
DOS.H included
# int handle;
# _dos_open("\\msc\\inc\\dos.h", 0, &handle)
0
# handle
7
# unsigned bytes;
# _dos_read(handle, p, 10240, &bytes)
0
# bytes
5917 (0x171D)
# _dos_close(handle)
0
# printf("%s\n", p) // display file
[FIGURE 2]
# char *s; // oops: forgot to initialize
# atoi(s)
## 492: Invalid address 0AA8:4582 at __CATOX+000E
# #reset
[FIGURE 3]
# char *p;
# p = malloc(2013)
address 03B8:01A6: ""
# p[2013] = 'x'
'x' (0x78)
[FIGURE 4]
# char *q;
# q = D16SegAbsolute(D16AbsAddress(p), 2013);
0C08:0000
[FIGURE 5]
# q[2013]
## 492: Invalid address 0BF8:002A in command line
# D16AbsAddress(p) == D16AbsAddress(q)
1
# D16SegLimit(p) == D16SegLimit(q)
0
# D16SegLimit(p)
24575 (0x5FFF)
# D16SegLimit(q)
2012 (0x7DC)
[FIGURE 6]
LSL (load segment limit) -- fetch size of a segment
LAR (load access rights) -- fetch access rights of segment
VERR (verify read) -- can segment be peeked?
VERW (verify write) -- can segment be poked?
SGDT (store GDT) -- fetch base address of GDT
SIDT (store IDT) -- fetch base addr of IDT
SLDT (store LDT) -- fetch selector to LDT
[FIGURE 7]
# char *p;
# p = D16MemAlloc(10240)
address 0C08:0000
# lsl(FP_SEG(p))
10239 (0x27FF)
[FIGURE 8]
unsigned i;
for (i=0; i<0xFFFF; i++) // for all possible selectors
if (lar(i)) // if a valid selector
printf("%04X\n", i); // print selector
[FIGURE 9]
0038 000000 LAR=93 LSL=FFFF PL=00 VERR VERW GDT
003C 000000 LAR=93 LSL=FFFF PL=00 VERR VERW LDT
0040 000400 LAR=93 LSL=0FFF PL=00 VERR VERW GDT TRANS
0044 000400 LAR=93 LSL=0FFF PL=00 VERR VERW LDT
0048 034FE0 LAR=93 LSL=FFFF PL=00 VERR VERW GDT
004C 034FE0 LAR=93 LSL=FFFF PL=00 VERR VERW LDT
0050 110010 LAR=93 LSL=200F PL=00 VERR VERW GDT
0054 110010 LAR=93 LSL=200F PL=00 VERR VERW LDT
0058 032050 LAR=81 LSL=0067 PL=00 GDT
005C 032050 LAR=81 LSL=0067 PL=00 LDT
0060 FA0000 LAR=93 LSL=FFFF PL=00 VERR VERW GDT
0064 FA0000 LAR=93 LSL=FFFF PL=00 VERR VERW LDT
0068 100010 LAR=82 LSL=FFF8 PL=00 GDT
[FIGURE 10]
for (i=0; i<0xFFFF; i++)
if (lar(i) && (i & 3))
printf("%04X PL=%02X\n", i, i & 3);
[FIGURE 11]
for (i=0; i<0xFFFF; i++)
if (lar(i) && (i == D16AbsAddress(MK_FP(i,0)) >> 4))
printf("%04X ", i);
[FIGURE 12]
typedef struct {
unsigned limit, lo;
unsigned char hi, reserved;
} GDTR;
[FIGURE 13]
# GDTR g;
# sgdt(&g)
# g
struct at 2F1C {
limit = 65528 (0xFFF8);
lo = 16 (0x10);
hi = '\020' (0x10);
reserved = '\0';}
[FIGURE 14]
typedef struct {
unsigned limit; // size minus 1
unsigned addr_lo; // physical base addr - paragraph.byte
unsigned char addr_hi; // physical base addr - megabyte
unsigned char access; // see ACCESS_RIGHTS below
unsigned reserved; // for 386 (32-bit)
} DESCRIPTOR;
[FIGURE 15]
# DESCRIPTOR *gdt; // GDT is array of DESCRIPTOR
# gdt = D16SegAbsolute((long) MK_FP(g.hi, g.lo), g.limit + 1)
address 0C08:0000
[FIGURE 16]
# gdt[FP_SEG(gdt) >> 3]
struct at 0C08:0C08 {
limit = 65527 (0xFFF7);
addr_lo = 16 (0x10);
addr_hi = '\020' (0x10);
access = 'Q' (0x91);
reserved = 0;}
[FIGURE 17]
typedef struct access {
unsigned accessed : 1; // has segment been accessed?
unsigned read_write : 1; // if data 1=write; if code 1=read
unsigned conf_exp : 1; // expansion direction
unsigned code_data : 1; // 0 = data, 1 = code
unsigned xsystem : 1; // 0 = system descriptor
unsigned dpl : 2; // protection level: 0..3
unsigned present : 1; // is segment in memory?
} ACCESS_RIGHTS;
# *((ACCESS_RIGHTS *) &gdt[FP_SEG(gdt) >> 3].access)
struct access at 0C08:0C0D {
accessed : 1 = 1; // it's been used
read_write : 1 = 0; // it's read-only
conf_exp : 1 = 0; // it's not a stack
code_data : 1 = 0; // it's data
xsystem : 1 = 1; // it's not a system descriptor
dpl : 2 = 0; // protection level 0
present : 1 = 1;} // it's present in memory