使用MASM-高级语法(1)

以前高级语言和汇编的最大差别就是条件测试、分支和循环等高级语法。高级语言中,程序员可以方便地用类似于ifcaseloopwhile等语句来构成程序的结构流程,不仅条理清楚、一目了然,而且维护性相当好。而汇编程序员呢?只能在cmp指令后面绞尽脑汁地想究竟用几十种跳转语句中的哪一种,这里就能列出近三十个条件跳转指令来:jajaejbjbejcjejgjgejljlejnajnaejnbjnbejncjnejngjngejnljnlejnojnpjnsjnzjojpjpejpojz等。虽然其中的很多指令我们一辈子也不会用到,但就是这些指令和一些looploopnz以及被loop涉及的ecx等寄存器纠缠在一起,使在汇编中书写结构清晰、可读性好的代码变得相当困难,这也是很多人视汇编为畏途的一个原因。

现在好了,MASM中新引入了一系列的伪指令,涉及条件测试、分支和循环语句,利用它们,汇编语言有了和高级语言一样的结构,配合对局部变量和调用参数等高级语言中常见元素的支持,为使用Win32汇编编写大规模的应用程序奠定了基础。

3.5.1  条件测试语句

在高级语言中,所有的分支和循环语句首先要涉及条件测试,也就是涉及一个表达式的结果是“真”还是“假”的问题,表达式中往往有用来做比较和计算的操作符,MASM也不例外,这就是条件测试语句。

MASM条件测试的基本表达式是:

寄存器或变量 操作符 操作数

两个以上的表达式可以用逻辑运算符连接:

(表达式1)逻辑运算符(表达式2 逻辑运算符(表达式3

允许的操作符和逻辑运算符如表3.5所示。

3.5  条件测试中的操作符

操作符和逻辑运算                                 

==

等于

变量和操作数之间的比较

!=

不等于

变量和操作数之间的比较

大于

变量和操作数之间的比较

>=

大于等于

变量和操作数之间的比较

续表     

操作符和逻辑运算                                

小于

变量和操作数之间的比较

<=

小于等于

变量和操作数之间的比较

&

位测试

将变量和操作数做“与”操作

!

逻辑取反

对变量取反或对表达式的结果取反

&&

逻辑与

对两个表达式的结果进行逻辑“与”操作

||

逻辑或

对两个表达式的结果进行逻辑“或”操作

举例如下,左边为表达式,右边是表达式为“真”的条件:

x==3              x等于3

eax!=3            eax不等于3

(y>=3)&&ebx       y大于等于3ebx为非零值

(z&1)||!eax       z1进行操作后非零或eax取反后非零

                     ;也就是说x的位0等于1或者eax为零

细心的读者一定会发现,MASM的条件测试采用的是和C语言相同的语法。如!&是对变量的操作符(取反和“与”操作),||&&是表达式结果之间的逻辑“与”和逻辑“或”,而==!=>< 等是比较符。同样,对于不含比较符的单个变量或寄存器,MASM也是将所有非零值认为是“真”,零值认为是“假”。

MASM的条件测试语句有几个限制,首先是表达式的左边只能是变量或寄存器,不能为常数;其次表达式的两边不能同时为变量,但可以同时是寄存器。这些限制来自于80x86的指令,因为条件测试伪操作符只是简单地把每个表达式翻译成cmptest指令,80x86的指令集中没有cmp 0,eax之类的指令,同时也不允许直接操作两个内存中的数,所以对这两个限制是很好理解的。

除了这些和高级语言类似的条件测试伪操作,汇编语言还有特殊的要求,就是程序中常常要根据系统标志寄存器中的各种标志位来做条件跳转,这些在高级语言中是用不到的,所以又增加了以下一些标志位的状态指示,它们本身相当于一个表达式:

CARRY?        表示Carry位是否置位

OVERFLOW?     表示Overflow位是否置位

PARITY?           表示Parity位是否置位

SIGN?         表示Sign位是否置位

ZERO?         表示Zero位是否置位

要测试eax等于ebx同时Zero位置位,条件表达式可以写为:

(eax==ebx) && ZERO?

要测试eax等于ebx同时Zero位清零,条件表达式可以写为:

(eax==ebx) && ! ZERO?

C语言的条件测试同样,MASM的条件测试伪指令并不会改变被测试的变量或寄存器的值,只是进行“测试”而已,到最后它会被编译器翻译成类似于cmptest之类的比较或位测试指令。

3.5.2  分支语句

分支语句用来根据条件表达式测试的真假执行不同的代码模块,MASM中的分支语句的语法如下:

.if    条件表达式1

        表达式1时执行的指令

[.elseif  条件表达式2]

        表达式2时执行的指令

[.elseif  条件表达式3]

        表达式3时执行的指令

[.else]

        所有表达式为时执行的指令

.endif

注意:关键字if/elseif/else/endif的前面有个小数点,如果不加小数点,就变成宏汇编中的条件汇编伪操作了,结果可是天差地别。

为了说明编译器究竟是如何处理这些伪指令的,先写一段如下的源代码:

.if       eax && (ebx >= dwX) || !(dwY != ecx)

          mov    esi,1

.elseif   edx

          mov    esi,2

.elseif   esi & 1

          mov    esi,3

.elseif   ZERO? && CARRY?

          mov    esi,4

.endif

然后反汇编:

;      .if eax

:00401000 0BC0                  or eax, eax

:00401002 7408                  je 0040100C

;      ebx = dwX

:00401004 3B1D00304000          cmp ebx, dword ptr [00403000]

:0040100A 7308                  jnb 00401014

;      dwY != ecx

:0040100C 390D04304000          cmp dword ptr [00403004], ecx

:00401012 7507                  jne 0040101B

:00401014 BE01000000         mov esi, 00000001

:00401019 EB23                  jmp 0040103E

;      elseif edx

:0040101B 0BD2                  or edx, edx

:0040101D 7407                  je 00401026

:0040101F BE02000000        mov esi, 00000002

:00401024 EB18                  jmp 0040103E

;      elseif esi & 1

:00401026 F7C601000000          test esi, 00000001

:0040102C 7407                  je 00401035

:0040102E BE03000000            mov esi, 00000003

:00401033 EB09                  jmp 0040103E

;      ZERO?

:00401035 7507                  jne 0040103E

;      CARRY?

:00401037 7305                  jnb 0040103E

:00401039 BE04000000        mov esi, 00000004

:0040103E                  

 

来源:电子工业出版社 作者:罗云彬

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汪宁宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值