📄 chapter10.htm
字号:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">
<Title>10.0-masm的优点</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="chapter9.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="chapter11.htm">下一章</A></TD>
</TR>
</TABLE>
<h2>10.0-masm的优点</h2>
<p>
如果你不在使用masm,你可以跳过这章并尝试着转换所有的例子,或不论如何地读一下,并试着说服自己使用masm。当然,这是你的选择。但masm真的使汇编语言更容易了。
</p>
<h2>10.1-条件和循环结构</h2>
<p>
Masm有一些伪高阶的语法来简便地创建条件和循环结构:
</p>
<p class="def1">
.IF, .ELSE, .ELSEIF, .ENDIF<br/>
.REPEAT, .UNTIL<br/>
.WHILE, .ENDW, .BREAK<br/>
.CONTINUE
</p>
<p>
<B>If</B>
</p><p>
如果你有使用编程语言的经验(你应该有),你可能已经看到了一些像if/else的结构:
</p>
<p class="def2">
.IF eax==1<br/>
;eax等于1<br/>
.ELSEIF eax=3<br/>
; eax等于3<br/>
.ELSE<br/>
; eax既不是1也不是3<br/>
.ENDIF
</p>
<p>
这种结构非常有用。你不需要和一对跳转搅在一起了,只要一个.IF语句(也不要忘记.IF和.ELSE之前的时期)。嵌套的if是允许的:
</p>
<p class="def2">
.IF eax==1<br/>
.IF ecx!=2<br/>
; eax= 1 而且 ecx 不是 2<br/>
.ENDIF<br/>
.ENDIF
</p>
<p>
但可以更简洁些:
</p><p class="def2">
.IF (eax==1 && ecx!=2)<br/>
; eax = 1 而且 ecx 不是 2<br/>
.ENDIF
</p><p>
这些是你可以使用的操作符:
</p>
<table>
<tr>
<td class="general2">==</td>
<td class="general3">等于</td>
</tr>
<tr>
<td class="general2">!=</td>
<td class="general3">不等于</td>
</tr>
<tr>
<td class="general2">></td>
<td class="general3">大于</td>
</tr>
<tr>
<td class="general2"><</td>
<td class="general3">小于</td>
</tr>
<tr>
<td class="general2">>=</td>
<td class="general3">大于等于</td>
</tr>
<tr>
<td class="general2"><=</td>
<td class="general3">小于等于</td>
</tr>
<tr>
<td class="general2">&</td>
<td class="general3">位测试</td>
</tr>
<tr>
<td class="general2">!</td>
<td class="general3">逻辑非</td>
</tr>
<tr>
<td class="general2">&&</td>
<td class="general3">逻辑与</td>
</tr>
<tr>
<td class="general2">||</td>
<td class="general3">逻辑或</td>
</tr>
<tr>
<td class="general2">CARRY?</td>
<td class="general3">carry bit set</td>
</tr>
<tr>
<td class="general2">OVERFLOW?</td>
<td class="general3">overflow bit set</td>
</tr>
<tr>
<td class="general2">PARITY?</td>
<td class="general3">parity bit set</td>
</tr>
<tr>
<td class="general2">SIGN?</td>
<td class="general3">sign bit set</td>
</tr>
<tr>
<td class="general2">ZERO?</td>
<td class="general3">zero bit set</td>
</tr>
</table>
<p>
<B>Repeat</B>
</p><p>
这个语句执行一块指令知道条件为真为止:
</p>
<p class="def2">
.REPEAT
;代码在此
.UNTIL eax==1
</p><p>
这块代码反复执行repeat和until之间的代码,知道eax=1。
</p><p>
<B>While</B></p>
<p>
While是repeat语句的反转。它在条件为真时执行代码块:
</p>
<p class="def2">
.WHILE eax==1<br/>
;代码在此<br/>
.ENDW
</p><p>
你可以使用.BREAK语句来跳出循环
</p><p class="def2">
.WHILE edx==1<br/>
inc eax<br/>
.IF eax==7<br/>
.BREAK<br/>
.ENDIF<br/>
.ENDW
</p><p>
如果Eax==7,while循环将停止
</p><p>
continue指令使repeat或While跳过下面的代码块,重新执行循环。
</p><h2>
10.2-invoke
</h2><p>
这是胜过tasm和nasm最大的优点。Invoke简化了过程和call的使用。
</p><p>
一般的格式:
</p><p class="def2">
push parameter3<br/>
push parameter2<br/>
push parameter1<br/>
call procedure
</p><p>
Invoke 格式:
</p><p class="def2">
invoke procedure, parameter1, parameter2, parameter3
</p><p>
汇编后的代码是一摸一样的,但invoke格式更简单而且更可靠。对一个过程使用invoke,你要这样定义prototype:
</p><p class="def1">
PROTO STDCALL testproc:DWORD, :DWORD, :DWORD
</p><p>
声明了名为testproc,需三个DWORD大小的参数的过程。现在,如果你这么做……
</p><p class="def2">
invoke testproc, 1, 2, 3, 4
</p><p>
……masm会给你一个testproc过程需要三个参数而不是四个的错误。Masm还会做类型检查。它检查参数是否为正确的类型(即大小)
</p><p>
在一个invoke语句中,你可以用ADDR代替offset。这会使地址在汇编时是正确的。
</p><p>
过程这样定义:
</p><p class="def2">
testproc PROTO STDCALL :DWORD, :DWORD, :DWORD
</p><p class="def2">
.code
</p><p class="def2">
testproc proc param1:DWORD, param2:DWORD, param3:DWORD
</p><p class="def2">
ret<br/>
testproc endp
</p><p>
这会创建一个名为testproc,带三个参数的过程。Prototype是用来调用过程的。
</p><p class="def2">
testproc PROTO STDCALL :DWORD, :DWORD, :DWORD
</p><p class="def2">
.code
</p><p class="def2">
testproc proc param1:DWORD, param2:DWORD, param3:DWORD
</p><p class="def2">
mov ecx, param1<br/>
mov edx, param2<br/>
mov eax, param3<br/>
add edx, eax<br/>
mul eax, ecx
</p><p class="def2">
ret<br/>
testproc endp
</p><p>
现在,过程做了一下计算,(param1, param2, param3) = param1 * (param2 + param3).结果(返回值)存放在eax中,局部变量这样定义:
</p><p class="def2">
testproc proc param1:DWORD, param2:DWORD, param3:DWORD<br/>
LOCAL var1:DWORD<br/>
LOCAL var2:BYTE
</p><p class="def2">
mov ecx, param1<br/>
mov var2, cl<br/>
mov edx, param2<br/>
mov eax, param3<br/>
mov var1, eax<br/>
add edx, eax<br/>
mul eax, ecx<br/>
mov ebx, var1<br/>
.IF bl==var2<br/>
xor eax, eax<br/>
.ENDIF
</p><p class="def2">
ret<br/>
testproc endp
</p><p>
你不可以在过程外使用这些变量。它们储存在栈中而且当过程返回时移出。
</p>
<h2>10.3-宏</h2>
<p>
现在不解释宏。可能在以后的教程中,但现在它们对我们不重要。
</p>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -