Quellcode durchsuchen

* More updates from Thomas

michael vor 25 Jahren
Ursprung
Commit
9963430a07
6 geänderte Dateien mit 464 neuen und 168 gelöschten Zeilen
  1. 68 0
      docs/go32ex/intpm.pas
  2. 15 17
      docs/go32ex/intpm.pp
  3. 102 0
      docs/go32ex/rmpmint.pas
  4. 65 77
      docs/go32ex/rmpmint.pp
  5. 150 0
      docs/go32ex/seldes.pas
  6. 64 74
      docs/go32ex/seldes.pp

+ 68 - 0
docs/go32ex/intpm.pas

@@ -0,0 +1,68 @@
+{ This example shows how to redirect a software interrupt by
+changing the protected mode handler of the DPMI host.
+
+In more detail it hooks interrupt 1Ch which is called every
+time the timer interrupt (int 08) is executed. This is the
+preferred way to hook the timer, because int 1Ch is a software
+interrupt which doesn't need so much initialization stuff
+compared to hooking a hardware interrupt.
+}
+
+uses
+	crt,
+	go32;
+
+const
+	{ interrupt number we want to hook }
+	int1c = $1c;
+
+var
+	{ 48 bit pointer to old interrupt handler }
+	oldint1c : tseginfo;
+	{ 48 bit pointer to new interrupt handler }
+	newint1c : tseginfo;
+
+	{ increased every time the interrupt is called  }
+	int1c_counter : Longint;
+
+	{ the current data selector }
+	int1c_ds : Word; external name '___v2prt0_ds_alias';
+
+{ the actual handler code }
+procedure int1c_handler; assembler;
+asm
+   cli
+{ save all registers }
+   pushw %ds
+   pushw %ax
+{ prepare segment registers for FPC procedure }
+   movw %cs:int1c_ds, %ax
+   movw %ax, %ds
+{ simply increase the counter by one }
+   incl int1c_counter
+{ restore registers }
+   popw %ax
+   popw %ds
+   sti
+   iret
+end;
+
+var i : Longint;
+
+begin
+     { insert right handler data into new handler variable }
+     newint1c.offset := @int1c_handler;
+     newint1c.segment := get_cs;
+     { get the old handler }
+     get_pm_interrupt(int1c, oldint1c);
+     Writeln('-- Press any key to exit --');
+     { set new handler }
+     set_pm_interrupt(int1c, newint1c);
+     { write the number of interrupts occured }
+     while (not keypressed) do begin
+           gotoxy(1, wherey);
+           write('Number of interrupts occured : ', int1c_counter);
+     end;
+     { restore old handler }
+     set_pm_interrupt(int1c, oldint1c);
+end.

+ 15 - 17
docs/go32ex/intpm.pp

@@ -1,27 +1,30 @@
-Program int_pm;
+uses
+	crt,
+	go32;
 
-uses crt, go32;
+const
+	int1c = $1c;
 
-const int1c = $1c; 
+var
+	oldint1c : tseginfo;
+	newint1c : tseginfo;
 
-var oldint1c : tseginfo;
-    newint1c : tseginfo;
-    int1c_counter : Longint;
+	int1c_counter : Longint;
+
+	int1c_ds : Word; external name '___v2prt0_ds_alias';
 
-{$ASMMODE DIRECT}
 procedure int1c_handler; assembler;
 asm
    cli
    pushw %ds
    pushw %ax
-   movw %cs:INT1C_DS, %ax
+   movw %cs:int1c_ds, %ax
    movw %ax, %ds
-   incl _INT1C_COUNTER
+   incl int1c_counter
    popw %ax
    popw %ds
    sti
    iret
-INT1C_DS: .word 0
 end;
 
 var i : Longint;
@@ -30,16 +33,11 @@ begin
      newint1c.offset := @int1c_handler;
      newint1c.segment := get_cs;
      get_pm_interrupt(int1c, oldint1c);
-     asm
-        movw %ds, %ax
-        movw %ax, INT1C_DS
-     end;
      Writeln('-- Press any key to exit --');
      set_pm_interrupt(int1c, newint1c);
      while (not keypressed) do begin
-           gotoxy(1, wherey); 
-           write('Number of interrupts occured : ', 
-                 int1c_counter);
+           gotoxy(1, wherey);
+           write('Number of interrupts occured : ', int1c_counter);
      end;
      set_pm_interrupt(int1c, oldint1c);
 end.

+ 102 - 0
docs/go32ex/rmpmint.pas

@@ -0,0 +1,102 @@
+{ This example shows the difference between protected and real mode
+interrupts; it redirects the protected mode handler to an own handler
+which returns an impossible function result and calls it afterwards.
+Then the real mode handler is called directly, to show the difference
+between the two.
+
+Used Interrupt:
+get DOS version Int 21h / function 30h
+     Input: AH = $30
+            AL = $1
+     Return: AL = major version number
+             AH = minor version number
+}
+
+uses
+	crt,
+	go32;
+
+var
+	r : trealregs;
+	{ temporary variable used for the protected mode int call }
+	axreg : Word;
+
+	oldint21h : tseginfo;
+	newint21h : tseginfo;
+
+{ this is our int 21h protected mode interupt handler. It catches
+the function call to get the DOS version, all other int 21h calls
+are redirected to the old handler; it is written in assembly
+because the old handler can't be called with pascal }
+procedure int21h_handler; assembler;
+asm
+	cmpw $0x3001, %ax
+	jne .LCallOld
+	movw $0x3112, %ax
+	iret
+
+.LCallOld:
+	ljmp %cs:oldint21h
+end;
+
+{ a small helper procedure, which waits for a keypress }
+procedure resume;
+begin
+	Writeln;
+	Write('-- press any key to resume --'); readkey;
+	gotoxy(1, wherey); clreol;
+end;
+
+begin
+	{ see the text messages for further detail }
+	clrscr;
+	Writeln('Executing real mode interrupt');
+	resume;
+	r.ah := $30; r.al := $01;  realintr($21, r);
+	Writeln('DOS v', r.al,'.',r.ah, ' detected');
+	resume;
+	Writeln('Executing protected mode interrupt without our own',
+		' handler');
+	Writeln;
+	asm
+		movb $0x30, %ah
+		movb $0x01, %al
+		int $0x21
+		movw %ax, axreg
+	end;
+	Writeln('DOS v', r.al,'.',r.ah, ' detected');
+	resume;
+	Writeln('As you can see the DPMI hosts default protected mode',
+		'handler');
+	Writeln('simply redirects it to the real mode handler');
+	resume;
+	Writeln('Now exchanging the protected mode interrupt with our ',
+		'own handler');
+	resume;
+
+	newint21h.offset := @int21h_handler;
+	newint21h.segment := get_cs;
+	get_pm_interrupt($21, oldint21h);
+	set_pm_interrupt($21, newint21h);
+
+	Writeln('Executing real mode interrupt again');
+	resume;
+	r.ah := $30; r.al := $01; realintr($21, r);
+	Writeln('DOS v', r.al,'.',r.ah, ' detected');
+	Writeln;
+	Writeln('See, it didn''t change in any way.');
+	resume;
+	Writeln('Now calling protected mode interrupt');
+	resume;
+	asm
+		movb $0x30, %ah
+		movb $0x01, %al
+		int $0x21
+		movw %ax, axreg
+	end;
+	Writeln('DOS v', lo(axreg),'.',hi(axreg), ' detected');
+	Writeln;
+	Writeln('Now you can see that there''s a distinction between ',
+		'the two ways of calling interrupts...');
+	set_pm_interrupt($21, oldint21h);
+end.

+ 65 - 77
docs/go32ex/rmpmint.pp

@@ -1,92 +1,80 @@
-Program rmpm_int;
+uses
+	crt,
+	go32;
 
-uses crt, go32;
-
-{$ASMMODE DIRECT}
-
-var r : trealregs;
-    axreg : Word; 
-
-    oldint21h : tseginfo;
-    newint21h : tseginfo;
+var
+	r : trealregs;
+	axreg : Word;
 
+	oldint21h : tseginfo;
+	newint21h : tseginfo;
 procedure int21h_handler; assembler;
 asm
-   cmpw $0x3001, %ax
-   jne CallOld
-   movw $0x3112, %ax
-   iret
-
-CallOld:
-   ljmp %cs:OLDHANDLER
+	cmpw $0x3001, %ax
+	jne .LCallOld
+	movw $0x3112, %ax
+	iret
 
-OLDHANDLER: .long 0
-            .word 0
+.LCallOld:
+	ljmp %cs:oldint21h
 end;
 
 procedure resume;
 begin
-     Writeln;
-     Write('-- press any key to resume --'); readkey;
-     gotoxy(1, wherey); clreol;
+	Writeln;
+	Write('-- press any key to resume --'); readkey;
+	gotoxy(1, wherey); clreol;
 end;
 
 begin
-     clrscr;
-     Writeln('Executing real mode interrupt');
-     resume;
-     r.ah := $30; r.al := $01;  realintr($21, r);
-     Writeln('DOS v', r.al,'.',r.ah, ' detected');
-     resume;
-     Writeln('Executing protected mode interrupt',
-             ' without our own handler');
-     Writeln;
-     asm
-        movb $0x30, %ah
-        movb $0x01, %al
-        int $0x21
-        movw %ax, _AXREG
-     end;
-     Writeln('DOS v', r.al,'.',r.ah, ' detected');
-     resume;
-     Writeln('As you can see the DPMI hosts',
-             ' default protected mode handler');
-     Writeln('simply redirects it to the real mode handler');
-     resume;
-     Writeln('Now exchanging the protected mode',
-             'interrupt with our own handler');
-     resume;
+	clrscr;
+	Writeln('Executing real mode interrupt');
+	resume;
+	r.ah := $30; r.al := $01;  realintr($21, r);
+	Writeln('DOS v', r.al,'.',r.ah, ' detected');
+	resume;
+	Writeln('Executing protected mode interrupt without our own',
+		' handler');
+	Writeln;
+	asm
+		movb $0x30, %ah
+		movb $0x01, %al
+		int $0x21
+		movw %ax, axreg
+	end;
+	Writeln('DOS v', r.al,'.',r.ah, ' detected');
+	resume;
+	Writeln('As you can see the DPMI hosts default protected mode',
+		'handler');
+	Writeln('simply redirects it to the real mode handler');
+	resume;
+	Writeln('Now exchanging the protected mode interrupt with our ',
+		'own handler');
+	resume;
 
-     newint21h.offset := @int21h_handler;
-     newint21h.segment := get_cs;
-     get_pm_interrupt($21, oldint21h);
-     asm
-        movl _OLDINT21H, %eax
-        movl %eax, OLDHANDLER
-        movw 4+_OLDINT21H, %ax
-        movw %ax, 4+OLDHANDLER
-     end;
-     set_pm_interrupt($21, newint21h);
+	newint21h.offset := @int21h_handler;
+	newint21h.segment := get_cs;
+	get_pm_interrupt($21, oldint21h);
+	set_pm_interrupt($21, newint21h);
 
-     Writeln('Executing real mode interrupt again');
-     resume;
-     r.ah := $30; r.al := $01; realintr($21, r);
-     Writeln('DOS v', r.al,'.',r.ah, ' detected');
-     Writeln;
-     Writeln('See, it didn''t change in any way.');
-     resume;
-     Writeln('Now calling protected mode interrupt');
-     resume;
-     asm
-        movb $0x30, %ah
-        movb $0x01, %al
-        int $0x21
-        movw %ax, _AXREG
-     end;
-     Writeln('DOS v', lo(axreg),'.',hi(axreg), ' detected');
-     Writeln;
-     Writeln('Now you can see that there''s',
-             ' a distinction between the two ways of ');
-     Writeln('calling interrupts...');
-     set_pm_interrupt($21, oldint21h);
+	Writeln('Executing real mode interrupt again');
+	resume;
+	r.ah := $30; r.al := $01; realintr($21, r);
+	Writeln('DOS v', r.al,'.',r.ah, ' detected');
+	Writeln;
+	Writeln('See, it didn''t change in any way.');
+	resume;
+	Writeln('Now calling protected mode interrupt');
+	resume;
+	asm
+		movb $0x30, %ah
+		movb $0x01, %al
+		int $0x21
+		movw %ax, axreg
+	end;
+	Writeln('DOS v', lo(axreg),'.',hi(axreg), ' detected');
+	Writeln;
+	Writeln('Now you can see that there''s a distinction between ',
+		'the two ways of calling interrupts...');
+	set_pm_interrupt($21, oldint21h);
 end.

+ 150 - 0
docs/go32ex/seldes.pas

@@ -0,0 +1,150 @@
+{
+This example demonstrates the usage of descriptors and the effects of
+changing its limit and base address.
+
+In more detail, the program fills the region described by an
+allocated descriptor in text screen memory with various characters.
+Before doing this it saves the entire screen contents to the heap and
+restores it afterwards.
+
+Some additional background:
+
+The text screen of a VGA card has it's address space at $B800:0;
+screen memory is organized in a linear fashion, e.g. the second line
+comes directly after the first, where each cell occupies 2 bytes of
+memory (1 byte character data, 1 byte attributes). It is 32 kb in
+size.
+
+Hence the offset of a single memory cell from its origin is:
+
+	Y * columns * 2 + X * 2
+
+where X and Y mark the point and columns is the number of character
+cells per line
+}
+{$mode delphi}
+uses
+	crt,
+	go32;
+
+const
+	{ screen x and y dimensions }
+	maxx = 80;
+	maxy = 25;
+	{ bytes used for every character cell }
+	bytespercell = 2;
+	{ screen size in bytes }
+	screensize = maxx * maxy * bytespercell;
+
+	{ the linear address of $B800:0 }
+	linB8000 = $B800 * 16;
+
+type
+	string80 = string[80];
+
+var
+	{ holds the old screen contents }
+	text_save : array[0..screensize-1] of byte;
+	{ old cursor x and y coordinates }
+	text_oldx, text_oldy : Word;
+
+	{ selector to the text mode screen }
+	text_sel : Word;
+
+{ prints a status message on the first line of the screen and then
+waits for a keypress }
+procedure status(s : string80);
+begin
+     gotoxy(1, 1); clreol; write(s); readkey;
+end;
+
+{ writes some descriptor info on the last 2 lines }
+procedure selinfo(sel : Word);
+begin
+     gotoxy(1, 24);
+     clreol; writeln('Descriptor base address : $',
+     	hexstr(get_segment_base_address(sel), 8));
+     clreol; write('Descriptor limit : ', get_segment_limit(sel));
+end;
+
+{ returns a 2 byte character cell, which includes character data
+and its color attributes }
+function makechar(ch : char; color : byte) : Word;
+begin
+     result := byte(ch) or (color shl 8);
+end;
+
+begin
+     { save original screen contents to variable, this time by using
+     seg_move() and the dosmemselector variable }
+     seg_move(dosmemselector, linB8000, get_ds, longint(@text_save),
+     	screensize);
+     { additionally we have to save the old screen cursor
+     coordinates }
+     text_oldx := wherex; text_oldy := wherey;
+     { clear the whole screen }
+     seg_fillword(dosmemselector, linB8000, screensize div 2,
+     	makechar(' ', Black or (Black shl 4)));
+     { output message }
+     status('Creating selector ''text_sel'' to a part of ' +
+     	'text screen memory');
+     { allocate descriptor }
+     text_sel := allocate_ldt_descriptors(1);
+     { set its base address to the linear address of the text screen
+     + the byte size of one line (=maxx * bytespercell * 1) }
+     set_segment_base_address(text_sel,
+     	linB8000 + bytespercell * maxx * 1);
+     { the limit is set to the screensize reduced by one (a must be)
+     and the number of lines we don't want to have touched (first
+     line + lower 2 lines) }
+     set_segment_limit(text_sel, screensize - 1 - bytespercell *
+     	maxx * 3);
+     { write descriptor info  }
+     selinfo(text_sel);
+
+     status('and clearing entire memory selected by ''text_sel''' +
+     	' descriptor');
+     { fill the entire selected memory with single characters }
+     seg_fillword(text_sel, 0, (get_segment_limit(text_sel)+1) div 2,
+     	makechar(' ', LightBlue shl 4));
+
+     status('Notice that only the memory described by the ' +
+     	'descriptor changed, nothing else');
+
+     status('Now reducing it''s limit and base and setting it''s ' +
+     	'described memory');
+     { set the base address of the descriptor (increase it by the
+     byte size of one line) }
+     set_segment_base_address(text_sel,
+     	get_segment_base_address(text_sel) + bytespercell * maxx);
+     { decrease the limit by byte size of 2 lines (1 line because
+     	base address changed, one line on the lower end) }
+     set_segment_limit(text_sel,
+     	get_segment_limit(text_sel) - bytespercell * maxx * 2);
+     { write descriptor info  }
+     selinfo(text_sel);
+     status('Notice that the base addr increased by one line but ' +
+     	'the limit decreased by 2 lines');
+     status('This should give you the hint that the limit is ' +
+     	'relative to the base');
+     { fill the descriptor area }
+     seg_fillword(text_sel, 0, (get_segment_limit(text_sel)+1) div 2,
+     	makechar(#176, LightMagenta or Brown shl 4));
+
+     status('Now let''s get crazy and copy 10 lines of data from ' +
+     	'the previously saved screen');
+     { copy memory from the data segment to screen }
+     seg_move(get_ds, longint(@text_save), text_sel,
+     	maxx * bytespercell * 2, maxx * bytespercell * 10);
+
+     status('At last freeing the descriptor and restoring the old ' +
+     	' screen contents..');
+     status('I hope this little program may give you some hints ' +
+     	'on working with descriptors');
+     { free the descriptor so that it can be used for things }
+     free_ldt_descriptor(text_sel);
+     { restore old state  }
+     seg_move(get_ds, longint(@text_save), dosmemselector,
+     	linB8000, screensize);
+     gotoxy(text_oldx, text_oldy);
+end.

+ 64 - 74
docs/go32ex/seldes.pp

@@ -1,40 +1,36 @@
-Program sel_des;
+{$mode delphi}
+uses
+	crt,
+	go32;
 
-uses crt,
-     go32;
+const
+	maxx = 80;
+	maxy = 25;
+	bytespercell = 2;
+	screensize = maxx * maxy * bytespercell;
 
-const maxx = 80;
-      maxy = 25;
-      bytespercell = 2;
-      screensize = maxx * maxy * bytespercell;
+	linB8000 = $B800 * 16;
 
-      linB8000 = $B800 * 16;
-
-type string80 = string[80];
+type
+	string80 = string[80];
 
 var
-    text_save : array[0..screensize-1] of byte;
-    text_oldx, text_oldy : Word;
+	text_save : array[0..screensize-1] of byte;
+	text_oldx, text_oldy : Word;
 
-    text_sel : Word;
+	text_sel : Word;
 
 procedure status(s : string80);
 begin
-  gotoxy(1, 1); 
-  clreol; 
-  write(s); 
-  readkey;
+     gotoxy(1, 1); clreol; write(s); readkey;
 end;
 
 procedure selinfo(sel : Word);
 begin
-gotoxy(1, 24);
-clreol; 
-writeln('Descriptor base address : $', 
-        hexstr(get_segment_base_address(sel), 8));
-clreol; 
-write('Descriptor limit : ', 
-       get_segment_limit(sel));
+     gotoxy(1, 24);
+     clreol; writeln('Descriptor base address : $',
+     	hexstr(get_segment_base_address(sel), 8));
+     clreol; write('Descriptor limit : ', get_segment_limit(sel));
 end;
 
 function makechar(ch : char; color : byte) : Word;
@@ -43,59 +39,53 @@ begin
 end;
 
 begin
-seg_move(dosmemselector, linB8000, 
-         get_ds, longint(@text_save), screensize);
-text_oldx := wherex; text_oldy := wherey;
-seg_fillword(dosmemselector, linB8000, 
-             screensize div 2, 
-             makechar(' ', Black or (Black shl 4)));
-status('Creating selector ' + 
-        '''text_sel'' to a part of text screen memory');
-text_sel := allocate_ldt_descriptors(1);
-set_segment_base_address(text_sel, linB8000 
-                          + bytespercell * maxx * 1);
-set_segment_limit(text_sel, 
-                  screensize-1-bytespercell*maxx*3);
-selinfo(text_sel);
+     seg_move(dosmemselector, linB8000, get_ds, longint(@text_save),
+     	screensize);
+     text_oldx := wherex; text_oldy := wherey;
+     seg_fillword(dosmemselector, linB8000, screensize div 2,
+     	makechar(' ', Black or (Black shl 4)));
+     status('Creating selector ''text_sel'' to a part of ' +
+     	'text screen memory');
+     text_sel := allocate_ldt_descriptors(1);
+     set_segment_base_address(text_sel,
+     	linB8000 + bytespercell * maxx * 1);
+     set_segment_limit(text_sel, screensize - 1 - bytespercell *
+     	maxx * 3);
+     selinfo(text_sel);
 
-status('and clearing entire memory ' + 
-       'selected by ''text_sel'' descriptor');
-seg_fillword(text_sel, 0, 
-             (get_segment_limit(text_sel)+1) div 2, 
-             makechar(' ', LightBlue shl 4));
+     status('and clearing entire memory selected by ''text_sel''' +
+     	' descriptor');
+     seg_fillword(text_sel, 0, (get_segment_limit(text_sel)+1) div 2,
+     	makechar(' ', LightBlue shl 4));
 
-status('Notice that only the memory described'+
-       ' by the descriptor changed, nothing else');
+     status('Notice that only the memory described by the' +
+     	' descriptor changed, nothing else');
 
-status('Now reducing it''s limit and base and '+
-       'setting it''s described memory');
-set_segment_base_address(text_sel, 
-     get_segment_base_address(text_sel) 
-     + bytespercell * maxx);
-set_segment_limit(text_sel, 
-     get_segment_limit(text_sel) 
-     - bytespercell * maxx * 2);
-selinfo(text_sel);
-status('Notice that the base addr increased by '+
-       'one line but the limit decreased by 2 lines');
-status('This should give you the hint that the '+
-       'limit is relative to the base');
-seg_fillword(text_sel, 0, 
-             (get_segment_limit(text_sel)+1) div 2, 
-             makechar(#176, LightMagenta or Brown shl 4));
+     status('Now reducing it''s limit and base and setting it''s ' +
+     	'described memory');
+     set_segment_base_address(text_sel,
+     	get_segment_base_address(text_sel) + bytespercell * maxx);
+     set_segment_limit(text_sel,
+     	get_segment_limit(text_sel) - bytespercell * maxx * 2);
+     selinfo(text_sel);
+     status('Notice that the base addr increased by one line but ' +
+     	'the limit decreased by 2 lines');
+     status('This should give you the hint that the limit is ' +
+     	'relative to the base');
+     seg_fillword(text_sel, 0, (get_segment_limit(text_sel)+1) div 2,
+     	makechar(#176, LightMagenta or Brown shl 4));
 
-status('Now let''s get crazy and copy 10 lines'+
-       ' of data from the previously saved screen');
-seg_move(get_ds, longint(@text_save), 
-         text_sel, maxx * bytespercell * 2, 
-         maxx * bytespercell * 10);
+     status('Now let''s get crazy and copy 10 lines of data from ' +
+     	'the previously saved screen');
+     seg_move(get_ds, longint(@text_save), text_sel,
+     	maxx * bytespercell * 2, maxx * bytespercell * 10);
 
-status('At last freeing the descriptor and '+
-       'restoring the old screen contents..');
-status('I hope this little program may give '+
-       'you some hints on working with descriptors');
-free_ldt_descriptor(text_sel);
-seg_move(get_ds, longint(@text_save), 
-         dosmemselector, linB8000, screensize);
-gotoxy(text_oldx, text_oldy);
+     status('At last freeing the descriptor and restoring the old '+
+     	' screen contents..');
+     status('I hope this little program may give you some hints on '+
+     	'working with descriptors');
+     free_ldt_descriptor(text_sel);
+     seg_move(get_ds, longint(@text_save), dosmemselector,
+     	linB8000, screensize);
+     gotoxy(text_oldx, text_oldy);
 end.