⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lib0027.html

📁 Memory Management—Algorithms and implementation in C/C++ Introduction Chapter 1 - Memory Manag
💻 HTML
📖 第 1 页 / 共 5 页
字号:
       <span style="background-color:d9d9d9">push   ebp</span>
       <span style="background-color:d9d9d9">mov    ebp, esp</span>

<span style="background-color:d9d9d9">; 17   :      strcpy(drone.firstname,"bill");</span>

       <span style="background-color:d9d9d9">push   OFFSET FLAT:$SG117</span>
       <span style="background-color:d9d9d9">push   OFFSET FLAT:_drone</span>
       <span style="background-color:d9d9d9">call   _strcpy</span>
       <span style="background-color:d9d9d9">add    esp, 8</span>

<span style="background-color:d9d9d9">; 18   :      strcpy(drone.lastname,"blunden");</span>

       <span style="background-color:d9d9d9">push   OFFSET FLAT:$SG118</span>
       <span style="background-color:d9d9d9">push   OFFSET FLAT:_drone+32</span>
       <span style="background-color:d9d9d9">call   _strcpy</span>
       <span style="background-color:d9d9d9">add    esp, 8</span>

<span style="background-color:d9d9d9">; 19   :      drone.age=35;</span>

       <span style="background-color:d9d9d9">mov    BYTE PTR _drone+64, 35    ; 00000023H</span>
<span style="background-color:d9d9d9">; 20   :      drone.salary=(int)(3.5);</span><a name="304"></a><a name="IDX-134"></a>
       <span style="background-color:d9d9d9">mov    DWORD PTR _drone+68, 3</span>

<span style="background-color:d9d9d9">; 21   :      return;</span>
<span style="background-color:d9d9d9">; 22   : }</span>

       <span style="background-color:d9d9d9">pop    ebp</span>
       <span style="background-color:d9d9d9">ret    0</span>
<span style="background-color:d9d9d9">_main  ENDP</span>
<span style="background-color:d9d9d9">_TEXT  ENDS</span>
<span style="background-color:d9d9d9">END</span>
</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&nbsp;</td><td valign="top" class="admon-body">
<p class="first-para">Microsoft has introduced a little bit of confusing nomenclature in the previous assembly code. Microsoft assembly code refers to its application's sections as "segments" (i.e., <span class="fixed">_TEXT SEGMENT</span>), but it is <i class="emphasis">not</i> the same thing as the memory segments described in the operating system's GDT. I have intentionally called these logical divisions of application memory "sections" to keep you from getting confused. If anything, Microsoft is using the term "segment" as a holdover from DOS, where addresses were specified with a segment and offset address.</p>
</td>
</tr>
</table>
<p class="last-para">The data section has a long and venerable history as the second oldest type of application memory section. In the old days, programs were just code and a fixed clump of static storage. The sysop was the only person with a console, punch cards were considered high-tech, and a top-of-the-line Dietzgen-Tyler Multilog slide rule with enamel finish cost $35.</p>
<a></a>
</div>
<div class="section">
<h3 class="sect3-title">
<a name="305"></a><a name="ch03lev2sec2"></a>Code Section</h3>
<p class="first-para">At the end of the day, an application's various sections are just bytes in memory. So in some special cases, you can get away with using a code section for data storage. In other words, it is possible to turn a code section into a data section. The magic rule to keep in mind is: It is data as long as you don't execute it. Here is an example:</p>
<div class="informalexample">
<pre class="literallayout">
<span style="background-color:d9d9d9">/* --codedata.c-- */</span>

<span style="background-color:d9d9d9">#include&lt;stdio.h&gt;</span>

<span style="background-color:d9d9d9">void code()</span>
<span style="background-color:d9d9d9">{</span>
    <span style="background-color:d9d9d9">/*</span>
    <span style="background-color:d9d9d9">on Intel, each instruction is 4 bytes:</span>
    <span style="background-color:d9d9d9">encoded as 0x66 0xb8 0x07 0x00</span>
    <span style="background-color:d9d9d9">*/</span>
    <span style="background-color:d9d9d9">_asm MOV AX,0x07</span>
    <span style="background-color:d9d9d9">_asm MOV AX,0x07</span>
    <span style="background-color:d9d9d9">_asm MOV AX,0x07</span>
    <span style="background-color:d9d9d9">_asm MOV AX,0x07</span><a name="306"></a><a name="IDX-135"></a>
    <span style="background-color:d9d9d9">/* 16 bytes total */</span>
    <span style="background-color:d9d9d9">return;</span>
<span style="background-color:d9d9d9">}</span>

<span style="background-color:d9d9d9">void main()</span>
<span style="background-color:d9d9d9">{</span>
    <span style="background-color:d9d9d9">char *cptr;</span>
    <span style="background-color:d9d9d9">short reg;</span>

    <span style="background-color:d9d9d9">code();</span>
    <b class="bold"><span style="background-color:d9d9d9">_</span></b><span style="background-color:d9d9d9">asm MOV reg,AX</span>
    <span style="background-color:d9d9d9">printf("reg=%d\n",reg);</span>

    <span style="background-color:d9d9d9">cptr = (char*)code;</span>
    <span style="background-color:d9d9d9">cptr[0]='d'; cptr[1]='a';cptr[2]='t';cptr[3]='a';</span>
    <span style="background-color:d9d9d9">cptr[4]=(char)0;</span>
    <span style="background-color:d9d9d9">printf("cptr[]=%s\n",cptr);</span>
    <span style="background-color:d9d9d9">return;</span>
<span style="background-color:d9d9d9">}</span>
</pre>
</div>
<p class="para">This can be built as a 16-bit DOS app with Turbo C+ + .</p>
<div class="informalexample">
<pre class="literallayout">
C:\TCC\codeData&gt;TCC -ms codedata.c
</pre>
</div>
<p class="para">The output you will get will look like this:</p>
<div class="informalexample">
<pre class="literallayout">
C:\TCC\codeData&gt;codedata
reg=7
cptr[]=data
</pre>
</div>
<p class="para">Before you rush out and try to write your own self-modifying app, I think you should know something: In the first chapter, I demonstrated how segments and pages can be marked as read-only, read-write, execute-only, etc. Some operating systems designate the pages belonging to code sections as execute-only, so you cannot always use the previously described trick because the memory in question cannot be read or modified. The above application worked fine running under DOS 6.22 because DOS has absolutely no memory protection.</p>
<p class="para">If you try to run the previous application on Windows via Visual Studio as a Win32 console application, the operating system will stop you in your tracks and present you with a dialog box like the one shown in <a class="internaljump" href="#ch03fig04">Figure 3.4</a>.</p>
<div class="figure">
<a name="307"></a><a name="ch03fig04"></a><span class="figuremediaobject"><a href="images/fig163%5F01%5F0%2Ejpg" NAME="IMG_53" target="_parent"><img src="images/fig163_01.jpg" height="70" width="230" alt="Click To expand" border="0"></a></span>
<br style="line-height: 1">
<span class="figure-title"><span class="figure-titlelabel">Figure 3.4</span></span>
</div>
<a name="308"></a><a name="IDX-136"></a>
<a></a>
</div>
<div class="section">
<h3 class="sect3-title">
<a name="309"></a><a name="ch03lev2sec3"></a>Stack</h3>
<p class="first-para">A stack is a sequence of bytes in memory that act like a first-in-last-out (FILO) data structure. Computer stacks typically "grow down." Each stack has a stack pointer (i.e., <span class="fixed">SP</span> in <a class="internaljump" href="#ch03fig05">Figure 3.5</a>) that stores the lowest address of the last item allocated on the stack. When a new item is added to the stack, the stack pointer is decremented to point to that item's first byte.</p>
<div class="figure">
<a name="310"></a><a name="ch03fig05"></a><span class="figuremediaobject"><img src="images/fig164_01.jpg" height="281" width="349" alt="" border="0"></span>
<br style="line-height: 1">
<span class="figure-title"><span class="figure-titlelabel">Figure 3.5</span></span>
</div>
<p class="para">There are two basic ways to manipulate a stack so memory can be allocated and freed: <span class="fixed">PUSH/POP</span> instructions and integer arithmetic.</p>
<p class="para">Every machine instruction set has a set of <span class="fixed">PUSH</span> and <span class="fixed">POP</span> instructions. The <span class="fixed">PUSH</span> instruction causes the stack pointer to be decremented. The space created by this operation will be populated by the <span class="fixed">PUSH</span> instruction's operand. The stack pointer will always point to the first byte of the data item on the top of the stack.</p>
<p class="para">The <span class="fixed">POP</span> instruction causes the stack pointer to be incremented. The storage reclaimed has its data stored in the <span class="fixed">POP</span> instruction's operand. The <span class="fixed">PUSH</span> and <span class="fixed">POP</span> operations are displayed in <a class="internaljump" href="#ch03fig06">Figure 3.6</a> to give you a better idea of how they function.</p>
<div class="figure">
<a name="311"></a><a name="ch03fig06"></a><span class="figuremediaobject"><a href="images/fig165%5F01%5F0%2Ejpg" NAME="IMG_55" target="_parent"><img src="images/fig165_01.jpg" height="290" width="350" alt="Click To expand" border="0"></a></span>
<br style="line-height: 1">
<span class="figure-title"><span class="figure-titlelabel">Figure 3.6</span></span>
</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&nbsp;</td><td valign="top" class="admon-body">
<p class="first-para">In <a class="internaljump" href="#ch03fig06">Figure 3.6</a>, I am assuming that I'm dealing with a native host that is <i class="emphasis">little</i> <i class="emphasis">endian</i>. Little endian architectures store the low-order bytes of a value in lower memory. For example, a value like 0x1A2B3C4D in memory would store 0x4D at byte (n), 0x3C at byte (n + 1), 0x2B at byte (n+2), and 0x1A at byte (n + 3).</p>
<div class="informaltable">
<table border="0">
<tbody>
<tr valign="top">
<td class="td" align="left">
<p class="table-para">address</p>
</td><td class="td" align="left">
<p class="table-para">n</p>
</td><td class="td" align="left">
<p class="table-para">n + 1</p>
</td><td class="td" align="left">
<p class="table-para">n+2</p>
</td><td class="td" align="left">
<p class="table-para">n + 3</p>
</td>
</tr>
<tr valign="top">
<td class="td" align="left">
<p class="table-para">byte</p>
</td><td class="td" align="left">
<p class="table-para">0x4D</p>
</td><td class="td" align="left">
<p class="table-para">0x3C</p>
</td><td class="td" align="left">
<p class="table-para">0x2B</p>
</td><td class="td" align="left">
<p class="table-para">0x1A</p>
</td>
</tr>
</tbody>
</table>
</div>
<p class="para">A <i class="emphasis">big endian</i> architecture stores the high-order bytes of a value in low memory:</p>
<div class="informaltable">
<table border="0">
<tbody>
<tr valign="top">
<td class="td" align="left">
<p class="table-para">address</p>
</td><td class="td" align="left">
<p class="table-para">n</p>
</td><td class="td" align="left">
<p class="table-para">n + 1</p>
</td><td class="td" align="left">
<p class="table-para">n + 2</p>
</td><td class="td" align="left">
<p class="table-para">n + 3</p>
</td>
</tr>
<tr valign="top">
<td class="td" align="left">
<p class="table-para">byte</p>
</td><td class="td" align="left">
<p class="table-para">0x1A</p>
</td><td class="td" align="left">
<p class="table-para">0x2B</p>
</td><td class="td" align="left">
<p class="table-para">0x3C</p>
</td><td class="td" align="left">
<p class="table-para">0x4D</p>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</table>
<a name="312"></a><a name="IDX-137"></a>
<p class="para">With manual stack pointer manipulation via direct arithmetic, storing and retrieving data is not as automated. Adding or subtracting values from the stack pointer does effectively change where <span class="fixed">SP</span> points, and this is a very fast way to allocate and free large amounts of storage on the stack. However, transferring data to and from the stack must be done manually. This is illustrated in <a class="internaljump" href="#ch03fig07">Figure 3.7</a>.</p>
<div class="figure">
<a name="313"></a><a name="ch03fig07"></a><span class="figuremediaobject"><a href="images/fig165%5F02%5F0%2Ejpg" NAME="IMG_56" target="_parent"><img src="images/fig165_02.jpg" height="160" width="227" alt="Click To expand" border="0"></a></span>
<br style="line-height: 1">
<span class="figure-title"><span class="figure-titlelabel">Figure 3.7</span></span>
</div>
<p class="para">The stack is a kind of temporary scratch pad that applications can use to keep track of short-lived values. The stack is particularly useful for operations that must be done and then undone. Thus, it is a good way to store and then reclaim temporary data. What distinguishes the stack from a free-for-all storage region, like the heap, is that there are rules that enforce a certain degree of regularity. In other words, the stack is predictable and the heap is chaotic. With the stack, you pretty much always know where the next chunk of <a name="314"></a><a name="IDX-138"></a>memory will start, regardless of how big or small the data item to be allocated is.</p>
<p class="para">The stack, though it might seem simple, is an extremely powerful concept when applied correctly. Stacks are used to implement high-level features like recursion and variable scope. Some garbage collectors use them as an alternative to a heap for more efficient allocation.</p>
<div class="section">
<h4 class="sect4-title">
<a name="315"></a><a name="ch03lev3sec1"></a>Activation Records</h4>
<p class="first-para">If you wanted to, you could use registers to pass parameter information to a function. However, using registers to pass parameters does not support recursion. Using the stack is a more flexible and powerful technique. Managing the stack to facilitate a function call is the responsibility of both the procedure that is invoking the function and the function being invoked. Both entities must work together in order to pass information back and forth on the stack. I will start with the responsibilities that belong to the invoking function.</p>
<p class="para">The following steps can be used to invoke a procedure and pass it arguments:</p>
<ol class="orderedlist">
<li class="first-listitem">
<p class="first-para">Push the current function's state onto the stack.</p>
</li>
<li class="listitem">
<p class="first-para">Push the return value onto the stack.</p>
</li>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -