home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
FOXPRO
/
FFAQ
/
UNDOC.FAQ
< prev
Wrap
Text File
|
1992-08-12
|
12KB
|
361 lines
FORCE FAQ (Frequently Asked Questions) (undoc.faq 1.1) 1
--------------------------------------------------------------------
Topic: UNDOCUMENTED FORCE FUNCTIONS Author: David Holmes
What you'll find here:
( ) General Discussion
( ) Function prototypes for the Undocumented functions
( ) Some quick documentation for them.
Examples: Attrs.exe ( in the SAMPLE directory )
General discussion:
-------------------------------------------------------------------
At long last, the documentation for the Undocumented FORCE
functions! Well, here's a quick list of the ones that I'm going
to talk about:
FUNCTION LOGICAL Interrupt
FUNCTION UINT Int_w_flags
PROCEDURE make_ptr
FUNCTION UINT and
FUNCTION UINT or
FUNCTION UINT xor
PROCEDURE dec_hex
And, here's the documentation in an orderly format:
===================================================================
Function: Interrupt()
---------
FORCE Prototype:
----------------
FUNCTION LOGICAL Interrupt PROTOTYPE
PARAMETERS VALUE UINT int_no, ;
VALUE UINT ax, VALUE UINT bx, ;
VALUE UINT cx, VALUE UINT dx, ;
VALUE UINT si, VALUE UINT di, ;
VALUE UINT bp, VALUE UINT ds, ;
VALUE UINT es
Description:
------------
This is the function that everyone thinks about when they hear
"Undocumented FORCE functions." Well, it's about time to remove
that "Undocumented" part.
First, a REALLY quick assembly language primer:
An Interrupt is exactly what you think it is. It "interrupts"
the CPU and has it attend to some task. To call an interrupt
(in assembly language), you say
INT 21h ; The major DOS interrupt
--------------------------------------------------------------------
(undoc.faq) 1
FORCE FAQ (Frequently Asked Questions) 2
--------------------------------------------------------------------
This tells the CPU to stop and save what it's doing, and jump
to some location specified at 0000:0084. From there, it looks
at the register AX, specifically the "top half," AH, and does
a CASE statement on it. For example, if AH were 4C, it would
terminate the current program and return to DOS. In assembly
that would look like:
MOV AX,4C00h ; The little h means Hexidecimal
INT 21h
To accomplish the same thing in FORCE, you would do:
VARDEF
UINT ax,bx,cx,dx,si,di,bp,ds,es
ENDDEF
AX = 0x4c00
Interrupt( 0x21, ax, bx, cx, dx, si, di, bp, ds, es )
That would effectively kill your program, and you'd just have
to hope that DOS closed all of your file handles for you. I
don't recommend this method of shutting down.
Another example: if AH was 09, the interrupt would mean "print
out a string pointed to by DS:DX." This would be a little
tougher in FORCE, but you could do it.
String_to_Print = "Must End with a Dollar Sign! $"
make_ptr( ds, dx, String_to_Print )
ax = 0x0900
Interrupt( 0x21, ax, bx, cx, dx, si, di, bp, ds, es )
Note that the Interrupt() function will change the "register"
values to what they were immediately after the interrupt
returned. Suppose that you wanted to know the free disk space
on your C drive. There's an interrupt service that will tell
you: Int 21h/36h. Here are the specs:
Registers on Entry:
------------------
AH = 36h
DL = Drive code ; 1 = A, 2 = B, 3 = C, etc
Registers on Return:
-------------------
AX = Sectors per cluster ; or 0xFFFF if error
BX = Available clusters
CX = Bytes per sector
DX = Clusters per drive
So, to get all of this information, you would do:
ax = 0x3600
dx = 0x0003
--------------------------------------------------------------------
(undoc.faq) 2
FORCE FAQ (Frequently Asked Questions) 3
--------------------------------------------------------------------
interrupt( 0x21, ax, bx, cx, dx, si, di, bp, ds, es )
if ax = 0xffff
? "Error!"
quit
endif
*- And to calculate the available space, you do
? "available space on C:"
?? AX * BX * CX
Interrupt() returns TRUE if the interrupt returned without the
carry flag set. Usually, the carry flag after an interrupt means
that there was some kind of error. If the carry flag was set,
FALSE is returned.
===================================================================
Function: Int_w_Flags
---------
FORCE Prototype:
FUNCTION UINT Int_w_Flags PROTOTYPE
PARAMETERS VALUE UINT int_no, ;
VALUE UINT ax, VALUE UINT bx, ;
VALUE UINT cx, VALUE UINT dx, ;
VALUE UINT si, VALUE UINT di, ;
VALUE UINT bp, VALUE UINT ds, ;
VALUE UINT es
Description:
------------
This function is exactly the same as Interrupt, but
instead of returning TRUE or FALSE, this returns the state
of the flags immediately after the interrupt. Since Int_w_Flags()
returns the flags as a UINT, you must use the function BITTEST()
to test the flags. For example, let's say you wanted to some
Direct Console I/O (INT 21h/06). The interrupt will return with
the Zero flag set if there was no character in keyboard buffer.
You would test that like this:
AX = 0x0600
DX = 0x00FF ; Fetch, don't write
do while .T.
flags = Int_w_Flags( 0x21,ax,bx,cx,dx,si,di,bp,ds,es)
*---
* To test the zero flag, use BITTEST() on the 6th bit
*---
if BitTest( flags, 6 ) ; Did we get a character?
continue; ; No, so continue.
else
exit
endif
enddo
--------------------------------------------------------------------
(undoc.faq) 3
FORCE FAQ (Frequently Asked Questions) 4
--------------------------------------------------------------------
===================================================================
Function: make_ptr()
---------
FORCE Prototype:
----------------
PROCEDURE make_ptr
PARAMETERS UINT segment, UINT offset, UNTYPED thing
Description:
------------
make_ptr() is pretty self explanatory. It takes the
address of something, and returns its SEGMENT and OFFSET. I
find this function particularly useful when I'm using the
Interrupt() and Int_w_Flags() functions. They often need a pointer
to a structure or a buffer, so you can use make_ptr() to get
that pointer. See the example code for Interrupt() above for its
usage.
===================================================================
Function: Addr
---------
FORCE Prototype:
FUNCTION ULONG Addr PROTOTYPE
PARAMETERS UNTYPED something
Description:
------------
Addr() returns the address of the "something." This is
useful if you need to pass a pointer to a C function, or just
need the address of any data type. It is similar to make_ptr(),
but returns the address as a ULONG value instead of splitting it
to a segment and offset, as make_ptr() does.
===================================================================
Function: And(), Or(), Xor()
---------
FORCE Prototypes:
-----------------
FUNCTION UINT and PROTOTYPE
PARAMETERS VALUE UINT word1, VALUE UINT word2
FUNCTION UINT or PROTOTYPE
PARAMETERS VALUE UINT word1, VALUE UINT word2
FUNCTION UINT xor PROTOTYPE
PARAMETERS VALUE UINT word1, VALUE UINT word2
Description:
------------
These functions implement three bitwise operations,
Logical AND, OR, and XOR. They each take two integer values,
--------------------------------------------------------------------
(undoc.faq) 4
FORCE FAQ (Frequently Asked Questions) 5
--------------------------------------------------------------------
and perform their logical function upon the two. The result
of that operation is returned.
For those of you not familiar with the logical operands, here's
a table, in binary, so that you can see how they work.
01001010 01001010 01001010
AND 00001010 OR 00101010 XOR 00101010
-------- -------- --------
00001010 01101010 01100000
If you can't figure it out, here it is in english:
AND will test two bits at a time, one from each word. The
resulting bit will be 1 if the first bit AND the second bit
are both 1.
OR will test two bits at a time, one from each word. The
resulting bit will be 1 if the first bit OR the second bit
OR both are 1. Known as the Inclusive-Or.
XOR will test two bits at a time, one from each word. the
resulting bit will be 1 if 1 and only 1 of the bits is 1.
If both are 1, the result is 0. If both are 0, the result
is 0. It is one or the other. Known as the Exclusive-Or.
*- Examples:
? and( 1, 3 ) && prints 1, because 1 and 3 look like:
&& 00000001 AND 00000011 ->
? or( 1, 4 ) && prints 5, because 1 and 4 look like:
&& 00000001 OR 00000100 -> 00000101
? xor( 1, 3 ) && Prints 2, because:
&& 00000001 XOR 00000011 -> 00000010
===================================================================
Function: Dec_Hex
---------
FORCE Prototype:
----------------
PROCEDURE Dec_Hex PROTOTYPE
PARAMETERS CONST CHAR result_buffer, VALUE LONG number
Description:
------------
Dec_Hex() is a strange procedure, but can sometimes be
useful. It takes a string buffer, and a LONG value, and prints
the value in Hexidecimal into the string buffer.
PROCEDURE Force_Main
VARDEF
CHAR buffer
ENDDEF
--------------------------------------------------------------------
(undoc.faq) 5
FORCE FAQ (Frequently Asked Questions) 6
--------------------------------------------------------------------
Dec_Hex( buffer, Addr( Force_Main )
? buffer && prints the address of FORCE_MAIN
ENDPRO
Note: This function is in the library, but with the leading
underscore (_). So I wrote a wrapper function called _dec_hex()
and included it in the COMMON.LIB. It does nothing more than
push the values on to the stack and call dex_hex().
===================================================================
Final Comments:
-------------------------------------------------------------------
I always get nervous talking about the undocumented FORCE
functions. They have a strange air of mystery about them, and
sometimes I wonder why they are undocumented. I have a feeling
it's because they don't really "fit in" with the general scheme
of the other functions in the library.
Nearly all of them deal with lower-level programming that
the designers probably wanted to hide from the user. Of course,
people found out about them, and many FORCE programmers don't
mind going low-level when it makes more sense. I suppose that's
why they're FORCE programmers.
If anyone thinks they know of any other undocumented
FORCE functions that they'd like to see tested and documented,
I'd be more than happy to oblige. Be sure that check out the
README.1ST in your \FORCE\BIN directory. It lists several
undocumented functions (which are in the header files).
Oh, don't bother to ask about the factorial() function.
It's not even supposed the be in the library, and calls some
functions that don't exist.
--------------------------------------------------------------------
(undoc.faq) 6