📄 lib0020.html
字号:
<span style="background-color:d9d9d9">asm "pop BX";</span>
<span style="background-color:d9d9d9">asm "pop AX";</span>
<span style="background-color:d9d9d9">asm "iret";</span>
<span style="background-color:d9d9d9">return;</span>
<span style="background-color:d9d9d9">}/*end ISR----------------------------------------------------*/</span>
<span style="background-color:d9d9d9">void printBiosCh(ch)</span>
<span style="background-color:d9d9d9">char ch;</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">/*</span>
<span style="background-color:d9d9d9">ch = BP + savedBP + retaddress</span>
<span style="background-color:d9d9d9">= BP + 4 bytes</span>
<span style="background-color:d9d9d9">*/</span>
<span style="background-color:d9d9d9">asm "MOV AH,0EH";</span>
<span style="background-color:d9d9d9">asm "MOV AL,+4[BP]";</span>
<span style="background-color:d9d9d9">asm "INT 10H";</span>
<span style="background-color:d9d9d9">return;</span><a name="150"></a><a name="IDX-55"></a>
<span style="background-color:d9d9d9">}/*end printBiosCh--------------------------------------------*/</span>
<span style="background-color:d9d9d9">void printBiosStr(cptr,n)</span>
<span style="background-color:d9d9d9">char* cptr;</span>
<span style="background-color:d9d9d9">int n;</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">int i;</span>
<span style="background-color:d9d9d9">for(i=0;i<n;i++){ printBiosCh(cptr[i]); }</span>
<span style="background-color:d9d9d9">return;</span>
<span style="background-color:d9d9d9">}/*end printBiosStr-------------------------------------------*/</span>
<span style="background-color:d9d9d9">/* wrestle control from DOS and go on a joy ride */</span>
<span style="background-color:d9d9d9">void main()</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">kbd_buffer = -1;</span>
<span style="background-color:d9d9d9">delay=0;</span>
<span style="background-color:d9d9d9">printBiosStr("save-",5);</span>
<span style="background-color:d9d9d9">saveOldISR();</span>
<span style="background-color:d9d9d9">printBiosStr("setUp-",6);</span>
<span style="background-color:d9d9d9">setUPISR();</span>
<span style="background-color:d9d9d9">readKBD();</span>
<span style="background-color:d9d9d9">while(delay<=7)</span>
<span style="background-color:d9d9d9">{</span>
<span style="background-color:d9d9d9">printBiosCh('1'+delay);</span>
<span style="background-color:d9d9d9">delay++;</span>
<span style="background-color:d9d9d9">readKBD();</span>
<span style="background-color:d9d9d9">}</span>
<span style="background-color:d9d9d9">printBiosStr("-restore",8);</span>
<span style="background-color:d9d9d9">restoreOldISR();</span>
<span style="background-color:d9d9d9">return;</span>
<span style="background-color:d9d9d9">}/*end main --------------------------------------------------*/</span>
</pre>
</div>
<p class="para">As with the previous example, I am using MICRO-C and MASM to build the executable. The steps necessary to build this program are:</p>
<div class="informalexample">
<pre class="literallayout">
del usurp.obj
del usurp.exe
del usurp.asm
mcp usurp.c | mcc > usurp.asm
ML /Zm -c usurp.asm
LINK usurp.obj PC86RL_S.OBJ
</pre>
</div>
<p class="para">Also, I use a trick in this example that might not be completely obvious. In C, labels are limited to the scope of the function that they are defined in. This prevents a nefarious programmer like me from making arbitrary random jumps from function to function.</p>
<a name="151"></a><a name="IDX-56"></a>
<p class="para">Naturally, there are exceptions to the rule. For example, <span class="fixed">longjmp()</span> and <span class="fixed">setjmp()</span> are ANSI C functions that allow nonlocal transfers of control. In addition, anyone who has abused exception handling knows that throwing an exception can be subverted to do an abrupt hop between procedures. The technique that I use is just not as conventional, or as obvious, as the previous two. I take advantage of the fact that assembly language labels tend to be global in scope.</p>
<p class="para">So instead of being limited to a function with ANSI C labels:</p>
<div class="informalexample">
<pre class="literallayout">
mylabel:
Printf("local function jump\n");
Goto mylabel;
</pre>
</div>
<p class="para">I surreptitiously hide the label definition inside of an inline assembly code snippet:</p>
<div class="informalexample">
<pre class="literallayout">
asm "my_global_label:";
</pre>
</div>
<p class="para">This effectively camouflages the label from the compiler's syntax checker. The only caveat is that you can only reference the label in other inline assembly statements.</p>
<p class="last-para">In the example above, I needed to specify an address without being constrained by C's structured programming paradigm. I needed this address to create a new entry in the IVT. Using the inline assembler tactic that I just explained, it worked fine.</p>
<a></a>
</div>
<div class="section">
<h3 class="sect3-title">
<a name="152"></a><a name="ch02lev2sec6"></a>Jumping the 640KB Hurdle</h3>
<p class="first-para">In the beginning, DOS programs lived in a 1MB jail cell. Escaping the conventional memory barrier was a lot like the sound barrier; it was just a matter of time before it was broken. In the later half of the 1980s, a number of products emerged that allowed extended memory to be accessed. These products may be referred to, in general, as <i class="emphasis">DOS extenders</i>. DOS extenders allowed the 640KB jail cell to grow into a 4GB prison.</p>
<blockquote class="blockquote">
<p class="first-para">"I am not a number; I am a free man."</p>
<p class="last-para">— Prisoner number 6, <I>The Prisoner</I>
</p>
</blockquote>
<table border="0" cellspacing="0" cellpadding="0" class="note">
<tr>
<td valign="top" class="admon-check"></td><td valign="top" class="admon-title">Note </td><td valign="top" class="admon-body">
<p class="first-para">A processor in real mode has a physical address space of 1MB. However, when all the storage dedicated to the BIOS, VRAM, and the IVT is taken into account, all that DOS is left with is less than 640KB of free space.</p>
</td>
</tr>
</table>
<p class="para">A DOS extender is a collection of library calls and software components that allow programs to manipulate extended memory but still access the DOS file system, system calls, and BIOS. Because <a name="153"></a><a name="IDX-57"></a>support must be compiled into a program, DOS extenders tended to be shipped with compilers as a sort of add-on third-party tool. For example, Visual C++ version 1.0 Professional was sold with Phar Lap's 286 | DOS Extender. Watcom's C compiler also came with Rational System's DOS/4G extender. DOS/4G is also still being sold by Tenberry Software. It may also be of interest to the reader that Phar Lap still sells a DOS extender. DOS may never die.</p>
<table border="0" cellspacing="0" cellpadding="0" class="note">
<tr>
<td valign="top" class="admon-check"></td><td valign="top" class="admon-title">Note </td><td valign="top" class="admon-body">
<p class="first-para">If you are interested in looking at a free DOS extender, take a look at DJGPP's cwsdpmi.exe DPMI host.</p>
</td>
</tr>
</table>
<p class="para">Because DOS is not designed to access extended memory, there was no established protocol for managing extended memory. Vendors selling DOS extenders were free to design their own unique bridge over the 1MB moat. Eventually, groups of companies got together and developed a number of standard ways to manage extended memory. A few of the more notable standards are:</p>
<ul class="itemizedlist">
<li class="first-listitem">
<p class="first-para">DOS Protected Mode Interface (DPMI)</p>
</li>
<li class="listitem">
<p class="first-para">Virtual Control Program Interface (VCPI)</p>
</li>
<li class="listitem">
<p class="first-para">eXtensible Memory Specification (XMS)</p>
</li>
</ul>
<p class="para">Each standard has a specification. The DPMI spec is available at Tenberry's site (see the reference section at the end of the chapter). The XMS standard was implemented by Microsoft, Lotus, and AST Research. The VCPI standard was an attempt to allow other DOS extenders to cohabitate with Expanded Memory Specification (EMS) services.</p>
<p class="para">The role of a DOS extender in the execution of a user application is displayed in <a class="internaljump" href="#ch02fig02">Figure 2.2</a>.</p>
<div class="figure">
<a name="154"></a><a name="ch02fig02"></a><span class="figuremediaobject"><a href="images/fig85%5F01%5F0%2Ejpg" NAME="IMG_24" target="_parent"><img src="images/fig85_01.jpg" height="196" width="252" alt="Click To expand" border="0"></a></span>
<br style="line-height: 1">
<span class="figure-title"><span class="figure-titlelabel">Figure 2.2</span></span>
</div>
<a name="155"></a><a name="IDX-58"></a>
<p class="para">The application itself runs in protected mode. The extender exposes an API to the application, which may look and smell like a normal 16-bit API. Beneath the API is a set of libraries that will manage the application's switch to protected mode and transmit its requests for real mode services. The client transmits these requests to a component that will do the necessary dirty work in real mode. According to the standard you are looking at, these worker components are called "drivers," "servers," or "hosts."</p>
<p class="para">The relationships between these different pieces remind me of a restaurant. The customer (i.e., the application) requests a specific entree from the waiter (i.e., the extender client). The waiter writes up the order and gives it to a cook (i.e., an XMS driver) in the back room. When the cook has completed the entree, he gives it to the waiter, who then passes it back to the customer. The kitchen, where the food is cooked, is real mode. The dining area, with its fancy linen, is protected mode.</p>
<p class="para">Most commercial DOS extenders will have client layers that are capable of interacting with a number of different extended memory environments. In fact, the first thing the client code usually does is check to see which environments exist. For example, the following code can be used by DOS extender clients to see if an XMS driver exists:</p>
<div class="informalexample">
<pre class="literallayout">
; Is an XMS driver installed?
mov ax,4300h
int 2Fh
cmp al,80h
jne NoXMSDriver
</pre>
</div>
<table border="0" cellspacing="0" cellpadding="0" class="note">
<tr>
<td valign="top" class="admon-check"></td><td valign="top" class="admon-title">Note </td><td valign="top" class="admon-body">
<p class="first-para">Vendors who sell DOS extenders often required the developer to embed all the memory management components in the application itself. The motivation behind this was to guarantee that the application could run on any DOS machine without having to impose a set of prerequisites. This tended to make applications using DOS extenders relatively large. Some DOS extenders were almost entire operating systems by themselves, especially when you compare them to DOS. It is rumored that DOS extender technology, at Microsoft, was first implemented in 1988 for a monster DOS application called Windows.</p>
</td>
</tr>
</table>
<p class="para">DOS 6.22 was released with two memory management drivers: <span class="fixed">HIMEM.SYS</span> and <span class="fixed">EMM386.EXE</span>.</p>
<p class="para">
<span class="fixed">HIMEM.SYS</span> is an XMS driver. It is mentioned in the XMS specification. <span class="fixed">EMM386.EXE</span> simulates expanded memory with extended memory for old dinosaur applications that need expanded memory. <span class="fixed">EMM386.EXE</span> provides services conforming to both the XMS and VCPI specifications.</p>
<a name="156"></a><a name="IDX-59"></a>
<p class="para">
<span class="fixed">HIMEM.SYS</span> and <span class="fixed">EMM386.EXE</span> are loaded into memory as device drivers when the operating system boots. The following entries in <span class="fixed">CONFIG.SYS</span> perform this task:</p>
<div class="informalexample">
<pre class="literallayout">
DEVICE=A:\DRIVER\HIMEM.SYS /VERBOSE
DEVICE=A:\DRIVER\EMM386.EXE VERBOSE
</pre>
</div>
<p class="last-para">Like DOS itself, DOS extenders have faded into obscurity. However, they serve as interesting, if not curious, artifacts that demonstrate just how far system software engineers are willing to go to solve a memory problem. They also show how problems related to backward compatibility can be extremely unpleasant.</p>
<a></a>
</div>
<a></a>
</div>
</div>
</div>
</div>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<td><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle" alt="Team LiB"></a></div></td>
<td valign="top" class="v2" align="right"><div STYLE="MARGIN-RIGHT: 0.15in"><a href="LiB0019.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0021.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr>
</table>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -