win32汇编学习笔记之选择结构

mac2026-09-02  2

汇编学习笔记整理之选择结构

鉴于之前学习代码的时候总是因为没有在课后整理笔记并且重新复习而导致知识点掌握不熟练的后果,现在将每次学习的笔记整理至csdn博客中。以便更好的督促自己学习

一、前览

选择结构可以使用.IF伪指令也可以使用条件转移指令Jcc和JMP配合实现。.IF伪指令比较简单但是不是最终的表示形式,汇编后的都要转化成相应的条件转移指令和无条件转移指令。

二、内容

1. .IF伪指令实现双分支结构

Ⅰ.语法解析:

语法格式图

.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

2. .IF•••.ELSEIF 伪指令实现多分支结构

语法格式: 用法参考.IF 伪指令

实例示范:

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

3. JMP和Jcc转移指令

JMP:无条件转移指令 Jcc :条件转移指令

Ⅰ.无条件转移指令JMP

JMP指令是从当前指令(JMP指令)的下一条指令位置无条件转移到另一个指令位置执行 该转移指令执行不影响任何标志位

Ⅱ.条件转移指令Jcc

条件转移指令是根据标志寄存器中的一个或多个标志位来决定是否转移。分为有符号数条件转移指令,无符号数条件转移指令和特殊算数标志位条件转移指令。

①.无符号转移指令 因为编辑器原因,在表格中||符号使用中文代替

指令关系检测条件功能描述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

4.浮点数的大小比较

实例示范:

.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
最新回复(0)