📄 chapter9.htm
字号:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">
<Title>9.0-更多的伪代码</Title>
<LINK REL="stylesheet" HREF="css/basestyles.css" TYPE="text/css">
<LINK REL="stylesheet" HREF="css/tutorials.css" TYPE="text/css">
</HEAD>
<BODY>
<h1 align="center">Win32Asm 教程 </h1>
<TABLE ALIGN="CENTER">
<TR>
<TD CLASS="tutnav" VALIGN="MIDDLE" WIDTH="60" HEIGHT="20"><A HREF="chapter8.htm">前一章</A></TD>
<TD CLASS="tutnav" VALIGN="MIDDLE" WIDTH="60" HEIGHT="20">
<A HREF="contents.htm">目录</A></TD>
<TD CLASS="tutnav" VALIGN="MIDDLE" WIDTH="60" HEIGHT="20"><A HREF="chapter10.htm">下一章</A></TD>
</TR>
</TABLE>
<h2>9.0-更多的伪代码</h2>
<p>
这儿有更多的伪代码
</p><table align="center" border="1" bordercolor="black">
<tr>
<td class="general1" width="80" align="center">TEST
</td>
</tr>
</table>
<p>
Test对两个参数(目标,源)执行AND逻辑操作,并根据结果设置标志寄存器。结果本身不会保存。Test用来测试一个位,例如寄存器:
</p><p class="def2">
test eax, 100b;b后缀意为二进制<br/>
jnz bitset
</p><p>
如果eax右数第三个位被设置了,jnz将会跳转。Test的一个非常普遍的用法是用来测试一方寄存器是否为空:</p>
<p class="def2">
test ecx, ecx<br/>
jz somewhere
</p><p>
如果ecx为零,Jz跳转
</p>
<table align="center" border="1" bordercolor="black">
<tr>
<td class="general1" width="160" align="center">关于栈的伪代码
</td>
</tr>
</table>
<p>
在我讲栈的伪代码之前,我会先解释什么是栈。栈是内存的一个地方,esp为指向栈的指针。栈是用来保存临时数值的地方,有两个指令来放入一个指和再把它取出来:push和pop。Push把一个指压入栈。Pop再把它弹出来。最后一个放入的值最先出来。一个值被放入栈中,栈指针步减,当它移出来的时候,栈指针步增。看这个例子:
</p><p class="def2">
(1) mov ecx, 100<br/>
(2) mov eax, 200<br/>
(3) push ecx ; save ecx<br/>
(4) push eax<br/>
(5) xor ecx, eax<br/>
(6) add ecx, 400<br/>
(7) mov edx, ecx<br/>
(8) pop ebx<br/>
(9) pop ecx
</p>
<p>
解释<br/>
1、 把100放入ecx中<br/>
2、 把200放入eax中<br/>
3、 把ecx(等于100)压入栈中(第一个压入)<br/>
4、 把eax(等于200)压入栈中(最后压入)<br/>
5、 /6/7:对ecx执行操作,使ecx的值改变<br/>
8、 弹出ebx:ebx成为200(最后压入,最先弹出)<br/>
9、 弹出ecx:ecx又成为100(最先压入,最后弹出)
</p><p>
为了说明再压栈和弹栈时,内存中发生了什么,看下图:
</p>
<table align="center">
<tr>
<td class="general2">Offset</td>
<td class="general3">1203</td>
<td class="general3">1204</td>
<td class="general3">1205</td>
<td class="general3">1206</td>
<td class="general3">1207</td>
<td class="general3">1208</td>
<td class="general3">1209</td>
<td class="general3">120A</td>
<td class="general3">120B</td>
</tr>
<tr>
<td class="general2">值</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
</tr>
<tr>
<td class="general2"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"><B>ESP</B> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
</tr>
</table>
<p align="center"><B> </B></p>
<p class="def1">
(栈在这里是初始化为0,但实际上并不是这样。ESP表示ESP指向的offset)
</p><p class="def2">
mov ax, 4560h<br/>
push ax
</p>
<table align="center">
<tr>
<td class="general2">Offset</td>
<td class="general3">1203</td>
<td class="general3">1204</td>
<td class="general3">1205</td>
<td class="general3">1206</td>
<td class="general3">1207</td>
<td class="general3">1208</td>
<td class="general3">1209</td>
<td class="general3">120A</td>
<td class="general3">120B</td>
</tr>
<tr>
<td class="general2">值</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">60</td>
<td class="general3">45</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
</tr>
<tr>
<td class="general2"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"><B>ESP</B></td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
</tr>
</table>
<p align="center"><B> </B></p>
<p class="def2">
mov cx, FFFFh<br/>
push cx
</p>
<table align="center">
<tr>
<td class="general2">Offset</td>
<td class="general3">1203</td>
<td class="general3">1204</td>
<td class="general3">1205</td>
<td class="general3">1206</td>
<td class="general3">1207</td>
<td class="general3">1208</td>
<td class="general3">1209</td>
<td class="general3">120A</td>
<td class="general3">120B</td>
</tr>
<tr>
<td class="general2">值</td>
<td class="general3">FF</td>
<td class="general3">FF</td>
<td class="general3">60</td>
<td class="general3">45</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
</tr>
<tr>
<td class="general2"> </td>
<td class="general3"><B>ESP</B> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
</tr>
</table>
<p align="center"><B> </B></p>
<p class="def2">
pop edx
</p>
<table align="center">
<tr>
<td class="general2">Offset</td>
<td class="general3">1203</td>
<td class="general3">1204</td>
<td class="general3">1205</td>
<td class="general3">1206</td>
<td class="general3">1207</td>
<td class="general3">1208</td>
<td class="general3">1209</td>
<td class="general3">120A</td>
<td class="general3">120B</td>
</tr>
<tr>
<td class="general2">值</td>
<td class="general3">FF</td>
<td class="general3">FF</td>
<td class="general3">60</td>
<td class="general3">45</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
<td class="general3">00</td>
</tr>
<tr>
<td class="general2"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"><B>ESP</B> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
<td class="general3"> </td>
</tr>
</table>
<p align="center"><B> </B></p>
<p>
edx现在是 4560FFFFh 了.
</p>
<table align="center" border="1" bordercolor="black">
<tr>
<td class="general1" width="140" align="center">CALL和RET
</td>
</tr>
</table>
<p>
Call跳转到某段代码而且一发现RET指令就返回。你可以把它们看成在其他编程语言中的函数或子程序。例如:
</p>
<p>
……代码……<br/>
call 0455659<br/>
……更多代码……
</p><p>
455659处的代码:
</p><p class="def2">
add eax, 500<br/>
mul eax, edx<br/>
ret
</p><p>
当执行这条指令时,处理器跳到455659处的代码,执行指令一直到ret为止,并返回到调用处的下一条。Call跳转到的代码被成为过程(procedure)。你可以把你反复使用的代码写进一个过程并在你每次需要它的时候调用。
</p><p>
更深入的细节:call把EIP(指向将要执行指令的指针)压入栈,而ret指令在它返回的时候把它弹出来。你也可以给一个call指定的参数。这是由压栈来完成的:
</p><p class="def2">
push something<br/>
push something2<br/>
call procedure
</p><p>
在一个调用的内部,参数从栈中读出并使用。注意,只在过程中需要的局部变量也储存在栈中。我不会在此深入下去,因为它可以在masm和tasm中很轻易的完称。只要记住你可以写过程,而且它们可以由参数。一个重要的地方:
</p><p>
eax几乎总是用来装一个过程的返回值。
</p><p>
对于windows函数也是如此。但然,你可以在你的过程使用其他的寄存器,但这是标准。
</p>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -