鉴于之前学习代码的时候总是因为没有在课后整理笔记并且重新复习而导致知识点掌握不熟练的后果,现在将每次学习的笔记整理至csdn博客中。以便更好的督促自己学习
选择结构可以使用.IF伪指令也可以使用条件转移指令Jcc和JMP配合实现。.IF伪指令比较简单但是不是最终的表示形式,汇编后的都要转化成相应的条件转移指令和无条件转移指令。
语法格式图
.IF 条件表达式
指令序列1
[.ELSE
指令序列2]
.ENDIF
例:
.IF x>=60
invoke printf,addr outfmt,x
.ELSE
invoke printf,addr outfmt,y
.ENDIF
补充:
①:条件表达式可用的关系运算符和C语言类似,有==(等于)、!=(不等于)、>、>=、<、<= 共6个。
②:如果有多个关系运算符则使用逻辑运算符进行连接。(常用逻辑运算符有&&、||、!),使用方法和C语言类似
注意:
①:C语言中的“&”(按二进制与)、“|”(按二进制或)、“~”(按二进制取反)和“^”(按二进制异或)在汇编语言中不能使用,需要实现这些功能要使用AND指令、OR指令、NOT指令、XOR指令
②:在汇编中运算符&&前后要使用空格隔开
.386 ;选择的处理器
.model flat, stdcall
option casemap:none ;指明标识符大小写敏感
include kernel32.inc ;要引用的头文件
includelib kernel32.lib ;要引用的库文件
includelib msvcrt.lib ;引用C库文件
scanf PROTO C:DWORD,:vararg ;C语言scanf函数原型声明
printf PROTO C:DWORD,:vararg;C语言printf函数原型声明
.data ;⑤数据段
fmt db '%d',0
x SDWORD ?
y DWORD 3
.code
start:
invoke scanf,addr fmt,addr x
.IF x<= 0
MOV EAX,x
invoke printf,addr fmt,EAX
.ENDIF
.IF SDWORD PTR x>0&&x<10
MOV EAX,x
IMUL EAX,x
invoke printf,addr fmt,EAX
.ENDIF
.IF x>= 10
MOV EAX,x
IMUL EAX,y
invoke printf,addr fmt,EAX
.ENDIF
ret
end start
fmt db '%d',0
outfmt db '%s',0
x DWORD ?
a BYTE '优秀',0
b BYTE '良好',0
m BYTE '中',0
n BYTE '及格',0
p byte '不及格',0
.code
start:
invoke scanf,addr fmt,addr x
.IF x>=80&&x<=89
invoke printf,addr outfmt ,addr b
.ELSEIF x>=70&&x<=79
invoke printf,addr outfmt ,addr m
.ELSEIF x>=60&&x<=69
invoke printf,addr outfmt ,addr n
.ELSEIF x>=0&&x<=59
invoke printf,addr outfmt ,addr p
.ELSE
invoke printf,addr outfmt ,addr a
.ENDIF
JMP:无条件转移指令
Jcc :条件转移指令
JMP指令是从当前指令(JMP指令)的下一条指令位置无条件转移到另一个指令位置执行
该转移指令执行不影响任何标志位
条件转移指令是根据标志寄存器中的一个或多个标志位来决定是否转移。分为有符号数条件转移指令,无符号数条件转移指令和特殊算数标志位条件转移指令。
①.无符号转移指令
因为编辑器原因,在表格中||符号使用中文代替
指令 | 关系 | 检测条件 | 功能描述 |
---|---|---|---|
JE/JZ | == | ZF=1 | – |
JNE/JNZ | != | ZF=0 | – |
JA/JNBE | > | CF=0&&ZF=0 | – |
JAE/JNB | >= | CF=0 | – |
JB/JNAE | < | CF=1 | – |
JBE/JNA | <= | CF=1或ZF=1 | – |
②.有符号条件转移指令
因为编辑器原因,在表格中||符号使用中文代替
指令 | 关系 | 检测条件 | 功能描述 |
---|---|---|---|
JE/JZ | == | ZF=1 | – |
JNE/JNZ | != | ZF=0 | – |
JG/JNLE | > | SF=OF&&ZF=0 | – |
JGE/JNL | >= | SF=OF或ZF=1 | – |
JL/JNGE | < | SF!=OF&&ZF=0 | – |
JLE/JNG | <= | SF!=OF或ZF=1 | – |
特殊算数标志位条件转移指令表格因为使用较少因此不做说明
.386 ;选择的处理器
.model flat, stdcall
option casemap:none ;指明标识符大小写敏感
include kernel32.inc ;要引用的头文件
includelib kernel32.lib ;要引用的库文件
includelib msvcrt.lib ;引用C库文件
scanf PROTO C:DWORD,:vararg ;C语言scanf函数原型声明
printf PROTO C:DWORD,:vararg;C语言printf函数原型声明
.data ;⑤数据段
fmt1 db '%d',0
x DWORD ?
.code
start:
invoke scanf,addr fmt1,addr x
MOV EAX,x ;取x
CMP EAX,0 ;和0比较
JG Great0 ;有符号转移指令:如果x>0转Great0否则直接结束
JMP DONE ;处理完x>0后转结束
Great0: ;处理x>0情况的入口点
CMP EAX,10 ;和10比较
JGE Great10 ;有符号转移指令:如果x>=10转Great10,否则执行IMUL EAX,x
IMUL EAX,x
JMP DONE
Great10: ;前面转Great10,即满足x>=10的条件时执行IMUL EAX,3
IMUL EAX,3
DONE:
invoke printf,addr fmt1,EAX
ret
end start
.386 ;选择的处理器
.model flat, stdcall
option casemap:none ;指明标识符大小写敏感
include kernel32.inc ;要引用的头文件
includelib kernel32.lib ;要引用的库文件
includelib msvcrt.lib ;引用C库文件
scanf PROTO C:DWORD,:vararg ;C语言scanf函数原型声明
printf PROTO C:DWORD,:vararg;C语言printf函数原型声明
.data ;⑤数据段
x qword ?
y qword ?
z qword ?
q qword ?
m qword -1.0
n qword 1.0
p qword 2.0
u qword 2.0
j qword 2.0
k qword 2.0
r qword 2.0
fmt db '%lf',0
fmt1 db '%.2lf',0
.code
start:
invoke scanf,addr fmt,addr x
FLD x
FSIN
fstp y
fld x
FCOS
fstp z
fld x
FMUL p
FSTP q
FEQU=40H
FLESS=1
FLD m
FCOMP x
fnstsw ax
.IF !(ah &(FLESS or FEQU))
invoke printf,addr fmt1,y
.ELSE
fld u
fsub n
fstp j
.ENDIF
FLD x
FCOMP n
fnstsw ax
.IF !(ah &(FLESS or FEQU))
invoke printf,addr fmt1,z
.ELSE
fld r
fsub n
fstp k
.ENDIF
FLD j
FCOMP k
fnstsw ax
.IF (ah &(FEQU))
invoke printf,addr fmt1,q
.ENDIF
ret
end start