|
|
#include <xdata.h>excode_t execseg(oldaddr, size) exdata_t oldaddr; unsigned size;
int unexecseg(addr) excode_t addr;
execseg is passed the current data address and size of the region to be executed and it returns the starting address of a region that is at least size number of bytes which can safely be branched to. On the Intel 8086 and 80286 processor, an alias CS descriptor is associated with the same memory as the data segment in which the oldaddr region lies. This means that offsets in the executable segment to access a given byte are essentially the same as the offsets in the original data segment, except the selector is different.
Note that excode_t and exdata_t are ``far'' pointers on the 8086 and 80286 and segment selectors on the 386. On an architecture where pages in the same ``segment'' are any combination of read/write/execute, the returned address is identical to the parameter passed to execseg.
We recommend that programs using this function on 8086- and 80286-based processors be large model, or that programmers be very familiar with ``hybrid model'' as well as with the use and misuse of far data.
When an error occurs, execseg returns((excode_t)-1), with errno set to ENONEM. Errors include an invalid data address or size, and an inability to allocate a new data selector.
The unexecseg system call disables an addr previously returned from execseg from being used as an executable region. Specifically, on the 8086 and 80286 architectures, this call frees the pointer used for the executable region. It returns 0 on success, or a -1 on error. For example, if addr is not an address returned by execseg, then a -1 is returned and it can be used as an executable region.
Since the execseg return value and address arguments are ``far'' pointers on 86 and 286 machines, any program including xdata.h must be compiled using the -Me option.
The following restrictions apply to the execute data system call.
Due to compiler confusion, you may get the message ``at least one void operand'' when using execseg. Please ignore it.
Under UNIX-386 the oldaddr parameter passed to execseg is a segment selector, not a pointer. execseg returns a selector value which provides a code segment alias to the original segment.
Similarly, the addr parameter passed to unexecseg is a selector value that has previously been returned by execseg.
Note that since execseg returns a segment selector on 386 machines, the return value from execseg is not directly useable in a C program. In an assembler program this selector value would be used as the top 16 bits of a 48 bit far pointer.