




已阅读5页,还剩165页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2020 3 21 1 第四章MASM下的Win32汇编语言语法 4 1程序框架4 2数据组织4 3子程序4 4程序流控制4 5宏4 6模块化程序设计4 7条件汇编4 8其它伪指令4 9实验工具的介绍和编程环境的创建 2020 3 21 2 4 1程序框架 CONST CODE 例如begin end endbegin 386是一条汇编器指令 也可称为伪指令 这条伪指令告诉汇编器程序中使用80386处理器的指令系统 MODEL也是一条伪指令 这条指令指示了当前程序的工作模式 内存模式 Win32程序只能使用Flat的内存模式 语言模式 规定了函数参数的压栈顺序及堆栈的恢复者 STDCALL语言模式 同于Windows的API函数的参数传递模式 2020 3 21 4 DATA DATA CONST STACK CODE是五个分段伪指令 DATA区间存放的是已经初始化过的变量 DATA 区间存放的是没有经过初始化的变量 CONST区间存放的是程序中的常量 只读 CODE区间是唯一存放代码的区间 该区间具有可执行的属性 只读 在Win32汇编程序中 不用考虑堆栈段 但特权级0的程序中 所有段都是可以读写的 end这条伪指令用来表示源程序的结束点 同时也指出了源程序的入口点 是从label标号开始的 它告诉汇编程序在遇到这条语句的时候结束对源文件的汇编工作 Label操作数可以取任何符合语法规则的标志符 是可选操作数 在多模块程序中 主模块程序中的end指令后必须带有Label操作数 而其他模块中的end指令后可以没有Label操作数 2020 3 21 6 注释 在MASM下的Win32汇编的注释是以分号 开始 直至行末 换行 Win32汇编程序默认每行一条语句 当源程序在一行中过长不便于阅读时 就可以用分行符 来分行书写 添加在语句末尾 2020 3 21 7 386 modelflat stdcall dataxdb10ydb120 codestart Moval xAddal yMovx alendstart 程序例子1 2020 3 21 8 返回 程序例子2 2020 3 21 9 4 2数据组织 4 2 1变量4 2 2数据类型4 2 3变量的访问4 2 4常量4 2 5汇编器的变量和常量 返回 2020 3 21 10 4 2 1变量 1 定义全局变量2 定义局部变量 返回 2020 3 21 11 1 定义全局变量 在Win32汇编程序里面 全局变量的作用域是整个模块 这些变量可以定义在 DATA或 DATA 段内 定义全局变量的格式 DATA段内 全局变量的定义可以是上面的任何方式 DATA 段内 全局变量的定义不允许有初值 只能用 代表初值为0 2020 3 21 12 一个关于全局变量定义的例子 变量定义的例子 Test Define asm 2020 3 21 13 数组变量的内存空间分布 从上表中 深灰色部分是变量Var1所占用的空间 淡灰色部分是变量Var2中的 3dup 1 2 3 部分 16进制地址 16个字节单元 没有 2020 3 21 14 在 Data段里面定义的变量在内存中的存在形式如下图所示 返回 2020 3 21 15 2 定义局部变量 从局部变量的作用域来看 它和标号很像 仅仅在它自己所在的子程序段里面有效 在不同的子程序里面可以有相同名称的局部变量 任何子程序里面的局部变量名都不能和已定义的全局变量名相同 定义局部变量的具体格式 在上面的格式中 关键字LOCAL一定要跟在子程序的proc关键字之后 其它指令之前 因为子程序一开始就要在堆栈里面先给局部变量保留好空间 局部变量无法初始化 只能在程序里用指令来赋值 2020 3 21 16 一个使用局部变量的例子 例子1定义了一个名为lca1的字节型变量 例子2定义了一个名为buffer大小为12个字节的数组变量 例子3定义了两个名为lca2和lca3的双字型变量 返回 当变量没有显式指出该变量的类型时 则默认其类型为DWORD 即双字类型 2020 3 21 17 4 2 2数据类型 1 简单数据类型2 结构体3 共用体4 记录 返回 2020 3 21 18 1 简单数据类型 MASM32中的所有其它数据类型都是通过简单数据类型组合或是更名 定义别名 而得来的 有些基本数据类型具有缩写形式 这些缩写形式只有在定义全局变量的时候才可以使用 字符串变量为字节变量 初始化时可以用双引号或者单引号来做定界符 并且可以和数值定义方法混用 当字符串变量初始值中带有双引号或者单引号本身时 则采用单引号或者双引号做定界符 Windows中字符串通常以0字节结尾 2020 3 21 19 简单数据类型一览表 表4 4 返回 2020 3 21 20 2 结构体 在MASM下的Win32汇编程序里面我们可以使用关键字STRUCT或它的同义关键字STRUC来定义一个我们所需的数据类型 结构体定义的格式如下所示 NONUNIQUE参数 关键字 用来告诉编译器必须使用结构体变量的成员变量的全名才能对其访问 2020 3 21 21 1 alignment参数的使用 定义了一个名为RECT的结构体 该结构体具有四个成员变量 在数据段中定义了一个RECT类型的变量rect 把该变量中的四个成员分别赋值为1 2 3 4 当参数alignment分别为1 2和4时 变量rect在内存中的分布情况如下 alignment分别为1 2和4时 按字节 字 双字对齐 2020 3 21 22 2 嵌套定义结构体 结构体成员变量的类型可以是字节 字 双字或任何已经定义过的数据结构类型 即在Win32汇编里面数据结构是可以嵌套定义的 但不可以进行递归定义 2020 3 21 23 3 结构体的初始化 DATArect1RECTrect2RECT DATA rect3RECT 如上定义结构体时 可以指定成员变量的初始值 默认值 该初始值只对在 DATA段内定义的变量有效 对在 DATA 段内定义的变量无效 按字节对齐 2020 3 21 24 4 结构体变量的定义 在MASM下的Win32汇编语言程序里面结构体变量的定义方法 POINTSTRUCTXbyte Ybyte POINTENDS DATAvar1POINTvar2POINT DATA var3POINT var4POINT 2020 3 21 25 5 结构体变量的访问 在MASM下的Win32汇编语言程序里面结构体变量的使用方法和高级语言里面结构体变量的使用方法很相似 即使用如下格式来访问结构体变量中的某个成员变量 对嵌套结构体类型的变量的访问实例 Movrect ltop x al 1 寄存器法赋值的两个例子 结构体变量的赋值 使用局部结构体变量的例子局部变量不能够在定义时初始化 只能通过子程序代码来赋值 上述两个例子效果相同 2020 3 21 27 返回 例 对子程序的结构体变量参数的赋值方法 Test struct asm 2 使用ASSUME关键字访问结构体变量 转41页 2020 3 21 28 例 定义结构数组 Studentstrucidbyte10dup 0 namebyte9dup 0 Studentends datastStudent60dup 2020 3 21 29 例 定义结构类型和变量POINTSTRUCTxDWORD yDWORD POINTENDSMSGSTRUCThwndDWORD messageDWORD wParamDWORD lParamDWORD timeDWORD ptPOINTMSGENDS datamymsgMSG 2020 3 21 30 3 共用体 共用体类型和结构体类型类似 由一个或者多个字段组成 各个字段可以有不同的数据类型 不同之处在于内存空间分配不同 结构体各字段有它们各自独立的内存 而共用体变量占用的内存字节数由它占有内存最多的字段决定 共用体中的每个成员偏移量都为0 都从共用体变量起始地址开始 2020 3 21 31 1 共用体类型的定义 name是定义的共用体类型名 通过它可以定义该种类型的共用体变量 Alignment参数和NONUNIQUE参数的含义和结构体定义中相同 字段定义是任何已有数据类型变量的定义语句 共用体还可以嵌套定义 在进行嵌套定义的时候 最外层的ENDS伪指令前面必须有共用体类型名 name 而非最外层的共用体的ENDS伪指令前面不需要有相应共用体的类型名 name 2020 3 21 32 两个共用体类型定义的例子 具有嵌套的共用体类型的定义 例2 定义一个共用体类型MYUNION 2020 3 21 33 2 共用体变量的定义 在共用体变量定义中 初始值同样可以给定也可以不给定 对于前面定义的共用体类型MYUNION 可以定义变量如下 firstmyunionMYUNIONsecondmyunionMYUNION 错误 改为 2020 3 21 34 3 共用体变量的访问 通过给出变量名和字段名 可以实现对变量某个字段的访问 例 MYUNIONUNIONfield1DWORD03fchfield2BYTE field3WORD MYUNIONENDSfirstxMYUNION Movfirstx Field2 06h 2020 3 21 35 Stustrucidbyte10dup 0 namebyte9dup 0 StuendsStdUNIONid1byte10dup 0 name1byte9dup 0 Stdends datast1Stu60dup st2Std60dup 问 上述定义中结构体类型名是 共用体类型名是 结构体变量名是 共用体变量名是 st1 st2在内存中各占多少字节 返回 2020 3 21 36 4 记录 记录类型由一个或多个成员组成 但成员被称为位段而非字段 因为它是由若干二进制位 而非字节 构成的 记录变量中的位段可以在常数表达式或者表达式中独立使用 记录类型的数据可以有效节省存储空间 记录类型的长度可以为1 2或4个字节 其中field的语法是 记录类型的定义 2020 3 21 37 1 记录类型的定义 recordname指明了记录类型名 fieldname指明了一个位段名 width指明了一个位段的宽度 位数 expression给出位段的初始值 在一个记录类型中可以定义一个或多个位段 每个位段可以由一个或多个位组成 定义的第一个位段在内存高端 其后定义的位段依次顺序排列 当一个记录类型所有位段宽度之和小于等于8时 这种记录类型宽度为一个字节 类似的 小于等于16或32位时 记录类型的宽度为2个字节或4个字节 此时 所有位段向内存低端靠齐 高位上的几个位无用 2020 3 21 38 记录类型定义的例子 firstREC有三个位段 位段aa占3个bit bb占3个bit cc占2个bit 且cc的初始值给定为 firstREC类型的记录变量占1B secondREC也由三个位段组成 位段ee占3个bit ff占5个bit gg占3个bit secondREC的位段总长是11个bit secondREC类型的记录变量占2B 最低3位 位 位 由位段gg使用 接着的 位 位 位 由位段ff使用 再接着的 位 位 位 由位段ee使用 最高的 位无意义 ee ff gg 2020 3 21 39 2 记录变量的定义 使用以下语法定义记录变量 name指定了记录变量名 recordname指定了记录类型名 initializer指定了记录变量相应位段的初始值 定义两个类型为firstREC和secondREC的记录变量 2020 3 21 40 3 记录变量的访问操作 记录类型有两个专用操作符 WIDTH用于返回记录位段的宽度 即该位段占用几位 MASK操作返回一个与记录类型同宽的整数 该整数把指定的位段都置为1 而把记录的其它位段置为0 NOTMASK操作正好和MASK相反 返回的整数中 指定的位段置为0 而其余的位段置为1 思考 使用记录变量名作为操作数时 返回什么 例 wequwidthaa w 3例 movah maskaa ah 11100000B 2020 3 21 41 使用记录类型名作为操作数时 返回一个与记录类型同宽的整数 有效位对应为1 无效位对应为0 例如 moval firstREC al 11111111Bmovax secondREC ax 0000011111111111B 使用位段名作为操作数时 返回该位段相对于记录类型起始位的偏移量 即该位段向右对齐时所需移位的次数 例如 moval aa al 5movah bb ah 2 使用记录类型变量名作为操作数时 返回该变量的值 例如 firstrecordfirstRECmoval firstrecord al 1 上面例子中定义的两个记录类型 firstREC和secondREC 使用WIDTH MASK两个操作符后有如下结果 使用记录变量一个完整的例子4 21 Access Record asm 返回 将bb位段置为全1 2020 3 21 43 4 2 3变量的访问 1 变量的一般访问方法2 类型操作伪指令3 地址计数器伪指令4 基数控制伪指令 返回 2020 3 21 44 1 变量的一般访问方法 返回 变量可以通过变量名来访问 对于数组变量 变量名做操作数时 则返回位移量为0的元素 dataVar3dw1122h 3344h 5566h 7788h codestart moveax offsetVar3movax Var3 2 ax 3344hmovesi 5movax Var3 esi ax 8855hinvokeExitProcess NULLendstart Test define asm 2020 3 21 45 2 类型操作伪指令 2020 3 21 46 类型操作伪指令 续表 2020 3 21 47 类型操作伪指令重点举例 OFFSET 返回地址表达式的偏移地址 作为立即数使用 汇编时求值 TYPE返回一个常数 表示变量的类型 对于BYTE WORD DWORD类型 分别返回字节数1 2 4 LENGTHOF返回直接分配给指定变量的元素个数 SIZE返回直接分配给指定变量的字节数 LENGTH TYPE Arraydw1 2 3 Addsi typearray Addsi 2 汇编后 a1dd 10dup 0 Type 4 lengthof 11 size 44 2020 3 21 48 例 feesdw100dup 0 Movcx typefees cx 2Movcx lengthoffees cx 100Movcx sizefees cx 200 2020 3 21 49 例 LENdb szdb WM NULL 0db WM CREATE 0db WM SIZE 0db WM PAINT 0db WM CLOSE 0db WM DESTROY 0 MovLEN sizeofsz LEN 8 2020 3 21 50 类型操作伪指令重点举例 返回 PTR 用于指定对变量或表达式访问的类型 格式 类型PTR表达式 格式一 PTR类型 格式二 格式一用于变量及变量表达式的强制类型转换 例 movwordptr ebx 2格式二用于指定某指针指向的数据类型 例如ASSUME伪指令 ASSUMEeax PTRPOINT 转24页 2020 3 21 51 3 地址计数器伪指令 1 地址计数器伪指令 2 ORG伪指令 返回 2020 3 21 52 1 地址计数器伪指令 当该伪指令位于某条指令语句中时 表示的地址是该语句的第一个字节的地址 如下例所示 在左面的例子程序执行后 寄存器中的内容如下 EAX 00404000H EBX 00403054H ECX 00401010H 分别为 data const code段的偏移地址 szData变量的三个双字内容一样 00404001H 返回 2020 3 21 53 例 xdd1dd2dd3dd4dd5dd6xLequ x sizeofdword xL 6 2020 3 21 54 2 ORG伪指令 ORG伪指令用来设置当前地址计数器的值 使用格式如下 这条ORG语句规定了程序段或数据块在该段内的起始地址 该地址由参数指定 必须能够求出一个常数 而且不能向前引用 返回 ORGexpression 使用ORG伪指令的例子 例4 27 2020 3 21 55 例 4 27 Test ORG asm dataDataPos ORG1Var1db0dh codestart moveax DataPos eax 00404000hleaebx Var1 ebx 00404001hinvokeExitProcess NULLendstart 返回 2020 3 21 56 4 基数控制伪指令 RADIX伪指令功能 设置默认的基数 基数值可以是2 16范围内的任何值 语法如下 expression表达式的值是要设置的整数基数 这个值可以是2 16的任何值 RADIX指令不影响浮点数或明确带有基数标记符的整数 上面例子中的eax里面的值为12345h 而ebx寄存器中的值为十进制的12345 返回 RADIXexpression 如果16进制数末位数为D 则不能省H 2020 3 21 57 4 2 4常量 整数型 实数型和字符串型这三种常量的定义格式如下 在整型数据的后面跟上基数标记符来告诉汇编程序要使用哪种格式的数据 三种格式数据和对应的基数标记符如下表所示 格式中的实数数据可以有两种方式来表达 十进制型和科学型 常量必须定义在 Const段内 与变量一样占用内存空间 但为只读属性 常量名类型数据 2020 3 21 58 一个具体的常量定义的例子 一个具体的例子 返回 constconst1db55hconst2Real4123 45c MyRECTMyRECT 若在指令中对上面的常量赋值 汇编虽然通过 但会出现如下警告 warningA4000 cannotmodifyREADONLYsegment 2020 3 21 59 4 2 5汇编器的变量和常量 返回 1 汇编期的变量和常量的定义格式2 汇编期变量3 汇编期常量 2020 3 21 60 1 汇编期的变量和常量的定义格式 在汇编时就用真实内容替代的变量和常量 MASM汇编程序在汇编前把程序中所有的汇编期的变量和常量都用它们所指示的真实内容来替代掉 然后才开始真正的语法检查等汇编工作 因为在程序的执行过程中不再需要这些汇编期的变量和常量 因此在程序中定义再多的汇编期的变量和常量也不会增加可执行文件的大小 汇编期的变量和常量的定义格式如下所示 汇编期的常量定义采用格式一和格式三 汇编期的变量定义采用格式二 汇编期的变量和常量可以定义在程序的任何地方 返回 最多可以定义4个字符 2020 3 21 61 2 汇编期变量 使用 关键字来定义 汇编期变量只能定义整数和不多于4个字符的字符串 汇编期变量可以重复定义 并保持其值至下一次重新定义前 汇编期变量可以定义在程序的任何地方 返回 num 1moval num al 1 num 5 movbl num bl 5num 1234 movedx num dx 31323334h numE 1000 constvardbnumEdup 2020 3 21 62 3 汇编期常量 汇编期常量可以使用textequ和equ关键字定义 汇编期常量可以分为 1 文本型汇编期常量 2 字符串型汇编期常量 3 数值型汇编期常量 返回 2020 3 21 63 1 文本型汇编期常量 汇编程序对源程序进行汇编的时候 会先把文本型汇编期常量所代替的文本直接放在源程序中 然后再进行汇编代码到机器码的转化工作 因此 文本型汇编期常量指示的字符串必须是有意义的 文本型汇编期常量可以重复定义 常量名textequ常量名equ 文本型汇编期常量的定义格式如下 2020 3 21 64 文本型汇编期常量举例 ChenbeitextequMovchenbei al 汇编时先变为Mov3 ebx edi alChenbeiequMovchenbei al 汇编到该语句时出错 undifinedsymbol OKConst1textequ 可以定义空常量 常用于条件汇编或宏中 注意 textequ只能定义文本型汇编期常量 返回 2020 3 21 65 2 字符串型汇编期常量 对程序中出现的字符串型的汇编期常量 汇编程序是用一串和字符串对应的ASCII码值来替换 然后再进行语法检查 字符串型汇编期常量不允许重复定义 在字符串型汇编期常量的定义格式如下 常量名equ 字符串 常量名equ 字符串 2020 3 21 66 字符串型与文本型汇编期常量对比举例 dataVar1db12h 34h 56h 77h 88h 99htextCequ 文本型汇编期常量StringCequ 3 ebx edi 字符串型汇编期常量movebx offsetVar1movedi 0moval textC 等效于moval 3 ebx edi 则al 77h movecx StringC 该行汇编出错 会报告 constantvaluetoolarge 因为ecx只能存放4个字符的ASCII码值 2020 3 21 67 对比举例 续 text1equ 文本型汇编期常量String1equ ebx 字符串型汇编期常量movebx 12345678hmoveax text1 eax 12345678hmovecx String1 ecx 00656278h 即字符串 ebx 返回 2020 3 21 68 数值型汇编期常量指常量的类型为整数和实数 定义格式如下 3 数值型汇编期常量 用equ关键字定义的数值型汇编期常量不允许重复定义 关键字equ的功能包括了关键字 和textequ所具有的功能 即用equ关键字除了可以定义整数和文本外 还可以来定义字符串和实数 常量名equ整数或实数 Minus3equ 3RealEequ9 99StringEquequ HelloWorld TxtEquequ 返回 2020 3 21 69 4 3子程序 1 子程序定义2 子程序调用3 子程序原型定义4 子程序举例 返回 2020 3 21 70 1 子程序定义 在Win32汇编语言里面子程序的定义格式如下所示 Label 子程序名Distance 子程序调用的距离 flat内存模式下忽略Distance属性 否则默认为NEAR LabelPROC distance LangType Visibility USESreglists parameter tag LOCALvarlist 局部变量定义statements 程序段ret 返回语句LabelENDP LangType 参数传递方式和堆栈的平衡方式 默认使用 model定义的值 参见表4 2 Visibitily 可见属性 PRIVATE PUBLIC EXPORT 2020 3 21 72 USESreglists Reglists是使用的寄存器名 空格区分 用于在前叙代码中将这些寄存器压栈 而在后续代码中将这些寄存器弹出 Parameter 参数 逗号区分 Tag 参数的类型 可以为任何有效类型或者VARARG 表明后面的参数个数不确定 默认为DWORD 返回 2020 3 21 73 子程序定义举例1 dataxdD codemyaprocUSESeaxa bmoveax aaddeax bmovx eaxretmyaendpstart invokemya 10 20endstart 2020 3 21 74 子程序定义举例1 反汇编后子程序PushebpMovebp espPusheaxMoveax dwordptrss ebp 8 eax 10Addeax dwordptrss ebp c Movx eaxPopeaxLeave movesp ebp popebpRet8 popeip esp 8 esp 反汇编后主程序Push14h b 20入栈Push0ah a 10入栈Callmya 2020 3 21 75 dataadd5bdd9 codemyaproca1 dword b1 dwordLOCALp1moveax a1 addra eaxmovebx b1 addrb eaxmovecx eax 5 ecxmovp1 ecx 5 p1incecx ecx 6mov eax ecx 6 amovecx p1 5 ecxmov ebx ecx 5 bretmyaendpstart invokemya offseta offsetbendstart 子程序定义举例2 2020 3 21 76 反汇编后子程序PushebpMovebp espAddesp 4Moveax dwordptrss ebp 8 movebx dwordptrss ebp c Movecx dwordptrDS eax Movdwordptrss ebp 4 ecxIncecxMovdwordptrds eax ecxMovecx dwordptrss ebp 4 Movdwordptrds ebx ecxLeave movesp ebp popebpRet8 popeip esp 8 esp 2020 3 21 77 子程序定义举例3 返回 MyProcPROCUSESEAXBXparxoreax eaxretMyProcENDP InvokeMyProc 123 MyProcPROCUSESEAXBXparpushebpmovebp esppusheaxpushbxxoreax eaxpopbxpopeaxleave movesp ebp popebpret4MyProcENDP 反汇编后为 2020 3 21 78 子程序定义举例4 返回 MyProcPROCUSESEAXBXparLOCALlv Dwordxoreax eaxretMyProcENDP InvokeMyProc 123 MyProcPROCUSESEAXBXparpushebpmovebp espaddesp 4pusheaxpushbxxoreax eaxpopbxpopeaxleave movesp ebp popebpret4MyProcENDP 反汇编后为 2020 3 21 79 2 子程序调用 使用CALL指令调用子程序的格式 使用STDCALL模式传递参数 2020 3 21 80 子程序调用 使用invoke伪指令来调用子程序 用invoke伪指令不仅使程序更方便编写 更具有可读性 而且也提高了程序的可靠性 因为invoke伪指令会根据子程序的原型定义来检查传递参数的类型和个数是否和子程序原型里规定的一样 如果调用一个没有参数的子程序或API函数 那么使用CALL指令和invoke伪指令效果就一样了 返回 InvokeMypro parameter1 parameter2 parameter3 2020 3 21 81 3 子程序原型定义 在Win32汇编程序里面 当子程序定义在调用语句之后 则需要在调用之前 先声明子程序的原型定义 子程序的声明格式如下所示 label表示要声明的子程序名 该名字必须和子程序定义里面proc关键字前面的那个名字相同 PROTO是子程序原型定义的关键字 在该关键字后面的内容是该子程序所具有的一些属性 子程序原型定义可以放在程序的任何地方 返回 2020 3 21 82 4 子程序举例 整数转化程序 这个程序的功能是把一个十进制整数的每一位都转化成对应的ASCII码 把它们保存到一个字符串缓冲区中 并显示 i2s2 asm 2020 3 21 83 1把一个十进制整数的每一位分开 设整数已存在dxax中 10 ebxj1 divebxpushedx 将余数压栈incecx 计数xoredx edxcmpeax 0jnzj1 2020 3 21 84 2将每个数转成ASCII码 存入EDI指向的地址j2 popeaxaddal 0 mov edi alincediloopj2movbyteptr edi 0 2020 3 21 85 szdb10dup 0 dtostrprocxmoveax xmovedi offsetszxoredx edxxorecx ecxmovebx 10j1 divebxpushedxincecxxoredx edxcmpeax 0jnzj1 invokedtostr 8192 j2 popeaxaddal 0 mov edi alincediloopj2movbyteptr edi 0retdtostrendp 返回 2020 3 21 86 4 4程序流控制 4 4 1 直接使用跳转指令4 4 2使用高级语言伪指令4 4 3 程序流控制举例 返回 2020 3 21 87 4 4 1直接使用跳转指令 1 程序语句标号的定义和使用2 特殊标号的定义和使用 返回 2020 3 21 88 1 程序语句标号的定义和使用 一般标号的定义格式如下 使用一般标号的例子 一般标号的作用域是它所在的子程序 在同一个作用域中 标号不能重名 Fun1proc jmppos1 pos1 xoreax ebx jmppos1 pos2 moveax ebxretFun1endpFun2proc jmppos1 pos1 xorebx ebx retFun2endp 标号名 目标指令格式一标号名 目标指令格式二 返回 2020 3 21 89 全局标号的作用域是整个程序 在主程序中定义的标号都是全局标号 也可以在子程序中定义一个全局标号 格式为 一个在子程序中定义全局标号的例子 Test Label asm例4 44 返回 全局标号 标号名 目标指令格式一标号名 目标指令格式二 2020 3 21 90 2 特殊标号的定义和使用 为了更方便程序里标号的定义 出现了特殊标号 一个子程序里面可以有多个 标号 标号可以重复定义 标号的引用 F表示本条指令后的第一个 标号 B标号表示本条指令前的第一个 标号 F和 B只会寻找最近的与它们匹配的那个 返回 Fun1proc jmp F xoreax ebx jmp B moveax ebxretFun1endp 2020 3 21 91 4 4 2使用高级语法伪指令 1 表达式操作符2 条件测试语句3 循环语句 返回 2020 3 21 92 1 表达式操作符 p159表4 10 比较操作符EQ NE GT LT GE LE 用来比较两个常数或两个同一段内的数据标志符 其具体含义 注意 不能用于比较寄存器和变量 不可构成单独的程序语句 这十个比较操作符用于在程序运行时比较两个操作数之间的关系 这十个比较操作符与前面的六个不同的是 它们可以比较常量 数据 寄存器和内存变量 具体使用方式 两个操作数按位与 结果非零即返回true 否则返回false 将两个操作数当作做逻辑变量 非零为真 零为假 然后做 与 操作 返回 与 结果 将两个操作数当作做逻辑变量 非零为真 零为假 然后做 或 操作 返回 或 结果 上面这十条关系操作符的实现使用CMP指令 因此对操作数的要求等同于CMP指令 不能两个操作数都是Mem类型 第一数据不能为立即数 数据的尺寸必须一样 datacnstequ5var1db3var2db4 codestart moveax 2movebx 3 ifvar2 cnstmoveax 0 endifinvokeExitProcess 0endstart ifvar1 var2错 ifcnst var2错 ifeax var1错 ifvar1LTcnst错 ifalLTcnst错 上面这十条关系操作符还可以和别的运行时操作符以及圆括号联合起来作为条件控制伪指令的判断条件 下面是这样的一个例子 if 5EQ4 eax ebx moveax 1 elsemoveax 0 endif AND OR XOR NOT SHL SHR 这六个操作符用于在程序运行时对整型常数操作数进行按位操作 除了整型常数 这几个操作符不能对其它类型的操作数进行操作 下表给出了这六个操作符具体含义和例子 其中A和B都是整型常数 0fffffffeh 表4 13这五个操作符分别代表标志寄存器里面的五个标志位 当相应的标志位被置位时 操作符就返回TRUE 否则返回FALSE 含义和使用方式 表4 13 2020 3 21 99 这五个操作符通常可以和其它能够用于程序控制伪指令的操作符一起来使用 如下例所示 返回 ifcarry ebx 1moveax 1 elsemoveax 0 endif 只有CF 1 ebx 1 才moveax 1 2020 3 21 101 2 条件测试语句 IF ELSEIF ELSE ENDIF 具体的使用格式如下所示 2020 3 21 102 编程练习 用条件测试语句实现判断x的符号的程序段 若x 0 则sx 0若x 0 则sx 1若x 0 则sx 1已知数据段如下 dataXdd 16Sxdb IFx 0Movsx 0 ELSEIFx 0Movsx 1 ELSEMovsx 1 ENDIF 返回 2020 3 21 103 3 循环语句 1 REPEAT系列伪代码 2 WHILE系列伪代码 3 BREAK伪代码 4 CONTINUE伪代码 返回 2020 3 21 104 1 REPEAT系列伪代码使用格式 REPEAT格式一程序代码 break if退出条件 continue UNTIL条件语句 返回 REPEAT格式二程序代码 break if退出条件 continue UNTILCXZ 条件语句 条件为真时退出循环条件为假时 返回循环体首部 循环体至少执行一次 首先 ECX 1条件为真或者ECX为零时退出循环 条件为假且ECX不为零时 返回循环体 可以没有 条件语句 循环体至少执行一次 UNTILCXZLoop 2020 3 21 105 2 WHILE系列伪代码使用格式 WHILE条件语句程序代码 break if条件语句 continue if条件语句 ENDW 返回 条件为假时跳过循环体 条件为真时 执行循环体 循环体可能不执行 2020 3 21 106 3 BREAK伪指令 BREAK伪指令的使用格式如下 返回 BREAK IFcondition 用于跳出 BREAK伪指令所在的循环体 当有条件测试语句 IF时 仅当条件为真时跳出循环体 否则继续执行循环体 2020 3 21 107 4 CONTINUE伪指令 CONTINUE伪指令的使用格式如下 CONTINUE IFcondition 用于结束 CONTINUE伪指令所在的循环体的本次循环 回到循环体的首部 开始下一次的循环过程 当有条件测试语句 IF时 仅当条件为真时结束本次循环 否则继续执行本次循环 2020 3 21 108 例4 51依次查找szString1中是否有字符 a 如果字符不为 a 则把字符直接存入szString2变量中 否则将字符 b 存入szString2 dataszString1db Thisisa 0szString2db256dup 0 codestart MOVESI offsetszString1MOVEDI offsetszString2 2020 3 21 109 whileTRUEMOVAL ESI break ifAL 0 如果到达字符串结尾 0 则使用break跳出循环 ifAL a MOVAL b MOV EDI ALINCESIINCEDI continue endif 否则直接把szString1中的字符存放到szString2缓冲区中 MOV EDI ALINCESIINCEDI endwinvokeMessageBox NULL addrszString2 addrszString2 MB OKinvokeExitProcess 0endstart 返回 2020 3 21 110 4 4 3程序流控制举例 分支程序实例 在这里例子程序中 用eax寄存器中的值作为随机数 该数除以7后的余数被保存到edx寄存器中 通过判断余数的数值来显示相应的日期信息 例4 52 asm 2020 3 21 111 例4 52用eax寄存器中的值作为随机数 该数除以7后的余数被保存到edx寄存器中 通过判断余数的数值来显示相应的日期信息 weekdb monday 0db tuesday 0db wednesday 0db thirsday 0db friday 0db saturday 0db sunday 0 2020 3 21 112 xoredx edx 把被除数的高位清零 以免溢出movnum 7 设置除数divnum 把eax寄存器中的值除以7 余数被保存到edx寄存器中 if edx 1 movebx 0 elseif edx 2 movebx 10 elseif edx 3 movebx 20 elseif edx 4 movebx 30 elseif edx 5 movebx 40 elseif edx 6 movebx 50 elseif edx 0 movebx 60 else出错处理 endifmoveax offsetweekaddeax ebx 2020 3 21 113 例4 53字符统计程序 要求统计出字符串 welcometousewin32assemblylanguage 中字符 s 出现的次数 并通过消息框报告统计结果 movebx 0 设定统计数字初始值0movecx offsetszTextmoval ecx while al 0 判断是否已经到字符串尾 ifal s incebx 当前字符为 s 统计数据加1 endifincecxmoval ecx 把下一个字符拷贝到al中 endw 把ebx中的整数转化成ASCII码字符串 并保存到szBuffer缓冲中invoke Translate ebx addrszBuffer 调用API函数 用消息框把字符串显示出来invokeMessageBox NULL offsetszBuffer offsetCaption 0 返回 2020 3 21 114 4 5宏 宏的定义宏的关键字宏与过程的比较宏与TEXTEQU的比较使用宏的好处和坏处 返回 2020 3 21 115 4 5 1宏的定义 宏是MASM汇编器一项功能强大的预处理命令 它和其它的预处理命令一样 在汇编器开始汇编代码之前就对宏进行了处理 它的定义格式如下 举例 宏的使用要经过3个步骤 1宏定义2宏调用3宏展开 2020 3 21 116 4 5 2宏的关键字 宏的基础语法关键字宏里面的循环指令关键字宏里面的条件测试关键字宏里面其它的关键字 返回 2020 3 21 117 宏的基础语法关键字 MACROMACRO关键字标志着整个宏的开始 在MACRO关键字的前面必须有一个name 这是该宏的名字 在汇编器汇编的时候将把程序里出现该name的地方都用该name对应的宏里面的内容来代替这个name 在MACRO关键字的后面可以跟上需要的参数 Endm结束一个宏 与MARCO关键字相配对 EXITM该关键字用来结束一个宏 功能就像ENDM关键字一样 并且在该关键字和ENDM之间的代码将都不被汇编 因此该关键字主要用于条件汇编 一个完整的宏的例子 上面例子中宏的name使用了RGB标识符 这个宏带了三个参数 分别为red green blue 该宏的作用是把这三个参数按顺序放到eax寄存器里面 最后的返回值默认为eax 使用宏 RGB1 2 3 Xoreax eaxMoval 3Roleax 8Moval 2Roleax 8Moval 1 2020 3 21 119 例 设计一个伪指令 将a b两个32位无符号数中较小的数赋给x minMACROa b xLOCALLpusheaxmoveax acmpeax bjbLmoveax bL movx eaxpopeaxENDM 若要用该宏实现V1 V2 V3这3各变量的比较并将最小值存入V该如何实现 注意 定义成局部标号可避免多次调用时产生重复标号 宏展开时 局部标号变为 0000 0001 FFFF V1dd40V2dd50V3dd20Vdd minV1 V2 VminV V3 V 2020 3 21 120 例 该宏实现了什么功能 moveMACROx ypushypopxENDM 返回 V1dw V2dw20 Movev1 v2 该宏实现了将的y值赋给x 2020 3 21 121 例4 55exitm的使用wmacroctifcteq0exitmendifwordctdup endm datamyword1dw8w8 等效于word8dup w0 等效于word0dup 2020 3 21 122 宏里面的循环指令关键字 FOR该关键字的使用格式如下 FORparameter REQ default statementsENDM该关键字的作用是用每个argument来代替statements里面的parameter并执行一遍statements过程 REQ表示parameter不能为空 default表示若没有给parameter传参数 则用default的内容代替 例4 57forsmacrocountforvalue ifvalueGTcount value取其后面的数 只要不大于count 就执行bytevalueexitmendifbytevalueendmendm datavar1dw11hfors3 等效于byte1 2 3 返回 2020 3 21 123 FORC该关键字的使用格式如下 FORCparameter statementsENDM该关键字的作用是用string里面的每个字符来代替statements里面的parameter并执行一遍statements过程 2020 3 21 124 宏里面的条件测试关键字 IF ELSEIF ELSE ENDIF 这些关键字的使用格式如下 IF条件表达式符合IF条件的程序过程 ELSEIF 条件表达式符合ELSEIF条件的程序过程 其它ELSEIF表达式 ELSE 符合ELSE条件的程序过程ENDIF 返回 2020 3 21 125 宏里面其它的关键字 我们在使用FOR关键字的时候经常会在后面的参数里用到尖括号 因为有些参数里面包含逗号 空格 分号等特殊的符号 当想把它们作为一个参数来处理 就需要用到尖括号 如下例 MyMacro 传递一个参数给MyMacro宏MyMacroone two three 传递三个参数给MyMacro宏 LOCAL在宏里定义局部变量 定义的格式如下 LOCALlocalname localname 其中localname是要定义的局部变量的变量名 PUSHCONTEXT和POPCONTEXT在宏里保
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年信息技术与信息管理基础知识考试试卷及答案
- 2025年小学语文知识考核试题及答案
- 2025年企业内部审计考试试卷及答案
- 2025年企业管理实务能力测试试题及答案
- 2025年美术学与设计专业考试题及答案
- 2025年公共管理学科试题及答案
- 2025年合同管理专业资格考试试卷及答案
- 2025年管理学考研复习试题及答案
- 2025年古典文学作品赏析考试试卷及答案
- 《小学二年级美术色彩搭配教学教案》
- GB/T 9254.1-2021信息技术设备、多媒体设备和接收机电磁兼容第1部分: 发射要求
- GB/T 40734-2021焊缝无损检测相控阵超声检测验收等级
- GB/T 24821-2009餐桌餐椅
- GB/T 20230-2022磷化铟单晶
- GB 6245-2006消防泵
- 清洁消毒记录
- 中考道德与法治复习要点+九年级中考道德与法治复习题
- 领导干部重大事项报告登记表
- 职业安全卫生培训讲义课件
- HPV与宫颈病变课件
- 环境有害物质管理标准
评论
0/150
提交评论