当前位置: 首页 > news >正文

电子商务网站建设与管理 李建忠深圳app推广平台

电子商务网站建设与管理 李建忠,深圳app推广平台,线上课程,网站301重定向的意义7. 高级汇编语言技术 文章目录 7. 高级汇编语言技术7.0 导学7.1 子程序的另外一种写法-segment/ends-proc/endp7.2 程序的多文件组织7.3 汇编指令汇总7.4 汇编伪操作汇总7.5 汇编操作符汇总7.6 汇编过程7.7 宏汇编7.8 宏库7.9 条件汇编7.10 重复汇编7.11 80x86汇编7.12 汇编语言…7. 高级汇编语言技术 文章目录 7. 高级汇编语言技术7.0 导学7.1 子程序的另外一种写法-segment/ends-proc/endp7.2 程序的多文件组织7.3 汇编指令汇总7.4 汇编伪操作汇总7.5 汇编操作符汇总7.6 汇编过程7.7 宏汇编7.8 宏库7.9 条件汇编7.10 重复汇编7.11 80x86汇编7.12 汇编语言集成开发环境7.13 用Visual studio开发汇编程序7.14 高级语言的指令级调试7.15 反汇编(逆向工程)7.16 混合编程7.17 文件结构分析7.18 完结撒花 参考视频烟台大学贺利坚老师的网课《汇编语言程序设计系列专题》或者是B站《汇编语言程序设计 贺利坚主讲》大家一起看比较热闹。中文教材《汇编语言-第3版-王爽》(课程使用)、《汇编语言-第4版-王爽》(最新版)。老师的博客《迂者-贺利坚的专栏-汇编语言》检测点答案参考《汇编语言》- 读书笔记 - 各章检测点归档 本篇笔记对应课程第七章下图倾斜章节划分和教材对应关系如下。 7.0 导学 目前我们已经跟随《汇编语言-王爽》完整系统的学完了8086汇编该教材体系清晰但是并没有提及汇编语言的可替代方案、以及一些汇编语言高级技术本章就对这部分没有提到的内容进行介绍。 本章参考教材 《IBM-PC汇编语言程序设计(第2版)》-沈美明-2018年出版《汇编语言基于x86处理器原书第7版》-[美]基普·欧文Kip Irvine著贺莲等译 8086扩展模块化功能设计支持的功能。 【7.1 子程序的另外一种写法】 【7.2 程序的多文件组织】将源程序写在多个文件中最后再组织在一起。 8086总结总结前面所有学过的指令、伪操作、操作符并介绍没用过的。 【7.3 汇编指令汇总】 【7.4 汇编伪操作汇总】 【7.5 汇编操作符汇总】 【7.6 汇编过程】 宏汇编在工程中常用类似于C语言中的宏定义。可以看到汇编语言对于工程上的支持还是比较强的。 【7.7 宏汇编】 【7.8 宏库】 【7.9 条件汇编】 【7.10 重复汇编】 32位汇编8086是16位汇编虽然目前的主流消费PC都是32位/64位但许多嵌入式等设备仍旧使用16位汇编另外16位汇编也可以迁移到32位/64位汇编所以学习16位汇编很有必要。基于前面的汇编语言工作方式进一步介绍32位汇编的80x86。 【7.11 80x86汇编】 【7.12 汇编语言集成开发环境】 【7.13 用Visual studio开发汇编程序】 实用技术对于汇编掌握熟练的人才能理解。 【7.14 高级语言的指令级调试】指令级调试。 【7.15 反汇编(逆向工程)】游戏外挂、文件解密、软件汉化等。 【7.16 混合编程】将汇编语言和高级语言混合进行编程同时发挥汇编语言执行效率高、高级语言开发效率高的优势。 【7.17 文件结构分析】通过debug等工具观察文件的每一个数据对照文件结构解析理解文件构成。以后即使遇到未知的文件结构也可以通过数据组成推导出文件结构。 7.1 子程序的另外一种写法-segment/ends-proc/endp 【名称 segment、名称 ends】 功能用于标记一个 段 的开始和结束。 【名称 proc、名称 endp】 功能用于标记一个 过程/子程序 的开始和结束。 前面我们直接定义一个子程序的地址标号带冒号标号来调用子程序但是总觉不够美观。实际上仿照C语言的方式我们可以进一步使用 proc/endp来进一步封装程序。比如下面给出的封装子程序的方式中间是正常调用使用ret返回右侧是远调用返回使用retf 图7-1 封装子程序 7.2 程序的多文件组织 图7-2 一般的程序和程序文件的关系 目前为止我们写的汇编程序都是将所有程序放在一个程序文件中。但实际上对于大型程序来说更加常见的做法是将不同的程序放在不同的程序文件中并且每个程序文件又会包含若干程序如上图所示。汇编语言中也很容易做到这点只需要在每个程序文件的最开始用 extrn声明要调用的外部程序、用 public声明可以被外部调用的程序最后再“分开编译、一起链接”即可和C中class的感觉有点像。具体操作见下面的示例 【代码示例】将上一小节“图7-1”所示的程序拆分成两个文件。 只存放主程序的程序文件 p-2-1.asm extrn subp:far ; 表示要调用的程序在其他文件far是调用属性assume cs:code, ss:stackstack segment stackdb 16 dup (0) stack endscode segment main procstart: ; 初始化mov ax,stackmov ss,axmov sp,16mov ax,1000; 调用子程序call far ptr subp; 程序退出mov ax,4c00hint 21h main endp code ends end start只存放子程序 subp 的程序文件 p7-2-2.asm public subp ; 列出本程序中可以被外部调用的程序assume cs:codecode segment subp proc; s: add ax,axadd ax,ax ; 子程序的开始也可以不加标号retf subp endp code ends end ; 注意子程序的最后就不需要标号了7.3 汇编指令汇总 图7-3 汇编指令分类 本小节总结一下汇编语言的所有指令并且简单介绍一下之前没学过的。但是要注意汇编指令很多没有必要全部记下来本节只是大概介绍一下有个印象后续用到的时候查手册就行。如上图给出常见的汇编指令分类下面进行简单的介绍 指令详解见《汇编语言指令大全》(Github、我的百度网盘)——根据字母表排序。 【一、数据传送指令】 【1-通用数据传送指令】mov、push、pop、xchg xchg 寄存器1,寄存器2交换指令交换(exchange)两个寄存器的内容。不影响标志位、寄存器不允许是使用段寄存器。 【2-累加器专用传送指令】in、out、xlat xlat换码指令将ds:[bxal]中的内容(8bit)放到al当中。显然这里的bx存储首地址、al存储偏移地址(显然不超过256)。换码指令不影响标志位。 【3-地址传送指令】lea、lds、les lea reg,src有效地址送寄存器指令。src 通常是标号这条指令就是将 src 的偏移地址送给寄存器 reg 中。只取两个字节。lds reg,src指针送寄存器和DS指令。将 src 作为偏移地址送给寄存器 reg、再将 (src2) 的内容作为首地址送给 ds。总共传送四字节。les reg,src指针送寄存器和ES指令。将 src 作为偏移地址送给寄存器 reg、再将 (src2) 的内容作为首地址送给 es。总共传送四字节。 【4-标志寄存器传送指令】lahf、sahf、pushf、popf lshf标志送AH指令(load ah flag)。将标志寄存器的低8位送给ah。sahfAH送标志寄存器指令(save ah flag)。将ah的内容保存到标志寄存器的低8位。pushf标志进栈指令。将标志寄存器压栈(16bit)。popf标志出栈指令。将标志寄存器出栈(16bit)。 【5-类型转换指令】cbw、cwd cbw将al扩展成ax(convert byte word)。ah的内容等于al的最高位。cwd将ax扩展成 dx,ax(convert word double word)。dx的内容等于ax的最高位。共性都是无操作符指令不影响标志寄存器。变化原则可保证有符号数不发生变化。 【二、算术指令】 【1-加法指令】add、adc、inc 【2-减法指令】sub、sbb、dec、neg(取负)、cmp 注cmp 的本质是减法只不过不影响操作数而是只影响标志寄存器。 【3-乘法指令】mul(无符号数乘法)、imul(有符号数乘法) 【4-除法指令】div(无符号数除法)、idiv(有符号数除法) 【5-十进制调整指令】daa、das、aaa、aas、aam、aad 前置知识1将一个十进制数用4位二进制进行表示称为“压缩的BCD码”比如(59)十进制(0101_1001)BCD用8位二进制进行表示就是“非压缩的BCD码”比如(59)十进制(0000_0101__0000_1001)BCD。ASCII码就是一种特殊的非压缩BCD码只不过高4位固定为0011b而不是0000b。 前置知识2现在做十进制加法。但是压缩的BCD码做二进制加法后需要再加 6d110h才能得到十进制加法结果。比如(198)十进制(0001_1001)BCD(0000_1000)BCD01100010_0001。可见十进制加法和二进制加法可以通过加减一个常数相互转化这个过程就是“调整”。 daa直接调用将二进制加法结果al调整为十进制。 das直接调用将二进制减法结果al调整为十进制。 aaa直接调用将ASCII码的十进制加法结果al调整为二进制。 aas直接调用将ASCII码的十进制减法结果al调整为二进制。 aam直接调用将ASCII码的十进制乘法结果ax调整为二进制。 aad直接调用将ASCII码的十进制除法结果ax调整为二进制。 【三、逻辑指令】 【1-逻辑运算指令】and、or、not、xor、test test本质上是进行 and操作。类似于cmp结果不保存只影响标志位常用于按位运算类型的判断。 【2-移位指令】shl/shr、sal/sar、rol/ror、rcl/rcr 【四、串处理指令】 【1-串方向标志】cld、std 【2-串重复前缀】rep、repe/repz、repne/repnz 【3-串处理指令】movsb/movsw、stosb/stoswsave、lodsb/lodswload、cmpsb/cmpsw、scasb/scaswscan 【代码示例】从附加段字符串computer中查找一个指定的字符t。 mess db COMPUTERlea di,mess mov al,T mov cx,8 ; 字符串长度为8所以最大重复8次 cld ; 自增方向 repne scasb ; 若当前内存单元a则退出扫描 ; 退出后若cx不为0则证明找到了指定字符t并且cx此时指明了位置。注课程首次出现见“5.14节-DF标志和串传送指令-movsb/movsw”。 【五、控制转移指令】 【1-无条件转移指令】jmp 【2-条件转移指令】jz/jne、je/jne、js/jns、jo/jno、jp/jnp、jb/jnb、jl/jnl、jbe/jnbe、jle/jnle、jcxz 注课程首次出现见“5.12节-cmp和条件转移指令”。 【3-循环指令】loop、loopz/loope、loopnz/loopne 【4-子程序调用和返回指令】call、ret 【5-中断与中断返回指令】int、into、iret 【六、处理机控制与杂项操作指令】 【1-标志处理指令】clc、stc、cmc、cld、std、cli、sti 【2-其他处理机控制与杂项操作指令】nop、hlt、wait、esc、lock nop无操作。机器码占一个字节。hlt暂停机。等待一次外中断之后继续执行程序。wait等待。等待外中断之后仍继续等待。esc换码。lock封锁。维持总线的锁存信号直到其后的指令执行完。 7.4 汇编伪操作汇总 图7-4 汇编伪操作分类 “汇编指令”对应机器指令在程序运行期间由计算机执行。而“伪操作”则是在汇编程序对源程序汇编期间由汇编程序处理的操作可以完成如数据定义、分配存储区、指示程序结束等功能。也就是说本节介绍的“伪操作”都是对汇编指令的简化伪操作本身并不对应机器指令但可以有效的分配内存空间改善程序可读性。 【一、处理器选择伪操作】 .8086选择 8086 指令系统。.286/.286P选择 80286 指令系统、选择保护模式下的 80286 指令系统。.386/.386P选择 80386 指令系统、选择保护模式下的 80386 指令系统。.486/.486P选择 80486 指令系统、选择保护模式下的 80486 指令系统。.586/.586P选择 Pentium 指令系统、选择保护模式下的 Pentium 指令系统。 【二、段定义伪操作】 之前一直在使用的段定义伪操作 assume有很多选项下面介绍完整的段定义伪操作。 .MODEL 存储模式 [,其他选项]assume 段寄存器:段名[,其他段声明] 段名 segment [定位类型] [组合类型] [使用类型] [类别] ... 段名 ends存储模式指定在内存中如何安放各段。可选参数有 tiny所有代码和数据在同一个段内全部加起来小于64K。small一个代码段和一个数据段都小于64K于是可以使用“近访问”。medium一个代码段和多个数据段。compact多个代码段和一个数据段。large多个代码段和多个数据段都小于64K都支持“远访问”。huge多个代码段和多个数据段并且允许单个数据结构超过64KB。flat用于保护模式下的平面内存模型。适用于32位或64位的操作系统如Windows所有代码和数据在一个4GB的线性地址空间内。 定位类型(align_type)段空间的对齐策略可选参数有BYTE以字节为单位、WORD字、DWORD双字、PAGE页。组合类型(combine_type)多文件组织时对于存储空间共享、段空间共享的策略。可选参数有PRIVATE私有段、PUBLIC公有段、COMMON、STACK栈段、AT、exp。使用类型(use_type)段使用内存的长度。可选参数有USE16、USE32。类别(class) 于是便可以使用伪操作对段的定义进行简化 ; 代码段 .code [name]; 数据段 .data ; 定义并初始化数据段。 .data? ; 定义但不初始化数据段没有给初始化值。 .fardata [name] ; 需要远访问的数据段 .fardata? [name]; 常量数据段 .const; 栈段 .stack [size]【代码示例】使用伪操作简化 Hello world! 程序。 【三、程序开始和结束伪操作】 TITLE text给程序加标题NAME module_name给程序加模块名END [label]程序结束标志里面的’label’就是标志程序开始的标号。.STARTUP取得数据段的段地址标志着程序的开始。masm5.0/5.1不支持需要更高版本。.EXIT [return_value]等价于调用21h中断的4ch号中断。masm5.0/5.1不支持需要更高版本。 【四、数据定义及存储器分配伪操作】 前面我们其实已经使用很多次数据段的定义定义时需要使用“助记符”指明数据类型。格式和常见示例如下 助记符DBbyte、DW16bit、DD双字、DF三字、DQ四字、DT五字。 ; 格式[变量] 助记符 操作数 [,操作数, …] [;注释]; 示例1定义不同类型的数据 DATA_BYTE DB 10,4,10H,? ; ? 表示随机值 DATA_WORD DW 100,100H,-5,? ; ? 表示随机值; 示例2数据的直接定址表 PAR1 DW 100,200 PAR2 DW 300,400 ADDR_TABLE DW PAR1,PAR2; 示例3使用dup快速定义数据 VAR DB 100 DUP (?) ; ? 表示随机值 DB 2 DUP (0,2 DUP(1,2),3) ; 嵌套使用dup但上述同一个内存空间定义好后就只能使用一种数据类型访问这显然非常不方便。于是还有一个伪操作 label可以使同一变量同一空间具有不同的类型。也就是从不同的角度使用同一段内存。 ; 变量名 LABEL type; 示例label需要写在数据段定义的上方 BYTE_ARRAY LABEL BYTE WORD_ARRAY DW 50 DUP (?) ; 使用标号WORD_ARRAY时以“字(16bit)”为单位操作内存。 ; 使用标号BYTE_ARRAY时以“字节(8bit)”为单位操作同一段内存。【五、表达式赋值伪操作】 汇编语言的伪操作 EQU可以将数值赋给表达式。重复定义时以最新定义为准。注意这些值都是编译前就能确定而不是需要执行机器指令才能得到。但注意EQU的功能没有C语言中的 #define具体见 “7.7节-宏汇编”。 ; 表达式名 EQU 表达式 ALPHA EQU 9 ; 使用ALPHA表示9 BETA EQU ALPHA18 ; 使用BETA表示91827 BB EQU [BP8] ; 使用BB表示偏移地址[bp8]内存单元中的值; 表达式名 表示式伪操作允许重复定义 EMP 7 ; 使用EMP表示7 EMP EMP1 ; 重复定义更新EMP为8; 实际应用下面三行等价 mov ax,betaemp ; 上面定义了beta27emp8 mov ax,35 mov ax,23h【六、地址计数器与对准伪操作】 ORG伪操作设置当前地址计数器的值。地址计数器 $ 保存当前正在汇编的指令的地址。ALIGN伪操作保证数组边界从2的整数次幂地址开始。对于16位/32位/64位操作系统有很大作用。EVEN伪操作使下一个变量或指令开始于偶数字节地址。 seg1 segment; org伪操作ORG 10 ; 偏移地址指定为10否则段开头默认为0VAR1 DW 1234HORG 20 ; 偏移地址指定为20VAR2 DW 5678H; 地址计数器$ORG $8 ; 偏移地址后移8VAR3 DW 1357H; align伪操作ALIGN 4 ; 偏移地址后移直到能被4整除ARRAY db 100 DUP(?); even伪操作A DB morning ; 奇数个地址EVEN ; 偏移地址后移直到第一个偶数地址B DW 2 DUP (?) ; 地址从偶数开始 SEG1 ENDS【七、基数控制伪操作】 .RADIX 表达式可以修改基数。不修改时计算过程默认使用十进制基数为十。 ; 默认基数是十进制 mov bx,0ffh ; 十六进制必须加后标显式声明 mov bx,178 ; 默认是十进制; 修改基数为十六进制 .RADIX 16 mov bx,0ff ; 此时默认是十六进制的00ffh mov bx,178d ; 十进制必须加后标显式声明7.5 汇编操作符汇总 图7-5 汇编操作符分类 “操作符”用于在操作数中通过操作符将常数、寄存器、标号、变量等组合成表达式实现求值的目的。这些值在汇编期间确定而不是在运行期间调用机器指令计算得到的。分类如上图现在来简单介绍。 【一、算术操作符】 五个操作符、-、*、/、Mod。 ; 利用立即数计算 BLOCK DB 25*80*2 DUP(?) ; 空间大小为4000个字节; 利用标号的偏移地址计算 ARRAY DW 1,2,3,4,5,6,7 ARYEND DW ? MOV CX, (ARYEND-ARRAY)/2; 常见应用 ADD AX, BLOCK2 ; 符号地址±常数常用 MOV AX, BX1 ; 编译时无法确定错误的代码 MOV AX, [BX1] ; 寄存器间接寻址【二、逻辑和移位操作符】 六个操作符AND、OR、XOR、NOT、SHL、SHR。 ; 应用实例一 OPR1 EQU 25 ; 也就是00011001B OPR2 EQU 7 ; 也就是00000111B AND AX, OPR1 AND OPR2 ; 等价于AND AX,1 MOV AX, 0FFFFH SHL 2 ; 等价于MOV AX,0FFFCH; 应用示例二 PORT_VAL 61H IN AL, PORT_VAL ; 等价于 in al,61H OUT PORT_VAL AND 0FEH, AL ; 只有最低位变成0也就是60H【三、关系操作符】 六个操作符EQ、NE、LT、LE、GT、GE。计算结果真为 0FFFFH假为 0000H。 MOV FID, (OFFSET Y - OFFSET X) LE 128 X: 代码... Y: 代码... ; 若 ≤128(真) 汇编结果等价于MOV FID,-1(有符号数) ; 若 128(假) 汇编结果等价于MOV FID,0【四、数值回送操作符】 五个操作符OFFSET取偏移地址、SEG取段地址、TYPE判断类型、LENGTH、SIZE。 type可能返回的值1(DB)、2(DW)、4(DD)、6(DF)、8(DQ)、10(DT)、-1(Near)、-2(Far)、0(常数)。length的功能回送由DUP定义的变量的单元数其它情况回送1。size的功能返回 length*type的值。 ARRAY DW 100 DUP (?) TABLE DB ABCDADD SI, TYPE ARRAY ; 等价于 ADD SI, 2 ADD SI, TYPE TABLE ; 等价于 ADD SI, 1 MOV CX, LENGTH ARRAY ; 等价于 MOV CX, 100 MOV CX, LENGTH TABLE ; 等价于 MOV CX, 1 MOV CX, SIZE ARRAY ; 等价于 MOV CX, 200 MOV CX, SIZE TABLE ; 等价于 MOV CX, 1【五、属性操作符】 八个操作符PTR、段操作符冒号 :、SHORT、THIS、HIGH、LOW、HIGHWORD、LOWWORD。 ; ptr指明数据类型属性 ; 调用格式类型 PTR 表达式 MOV WORD PTR [BX], 5; 段操作符“:” MOV ES:[BX], AL ; bx的段地址默认时ds若不是必须指明段地址。; short标明是短转移 ; 调用格式SHORT 标号 JMP SHORT NEXT; 将紧跟在this后面的数据类型作为当前数据 ; 调用格式THIS 类型 TA EQU THIS BYTE TD DW 1234H NEXT EQU THIS FAR MOV AX,2; HIGH和LOW可以分别取出高字节、低字节 CONS EQU 1234H MOV AH, HIGH CONS MOV AL, LOW CONS7.6 汇编过程 图7-6 生成可执行.exe文件的过程 目标文件OBJ包含了可重定位的机器代码和符号信息。交叉引用文件CRF包含标识符(段名、过程名、变量名、标号)在源程序中定义的位置和被引用的位置对源程序所用的各种符号进行前后对照的文件。CRF文件 是一个二进制文件不能直接读取可以通过 cref 软件将其转换成文本文件查看。列表文件LST将源程序、目标程序、错误信息列表以供检查程序用。信息全面用于早期的调试。 注“3.2节-由源程序到程序运行”已经介绍过。 前面已经介绍过.exe文件由汇编、连接得到如上图那么具体的汇编过程是什么样子呢汇编过程将源文件转换成目标文件需要经过两次扫描如下 第一次汇编确定地址翻译成各条机器码字符标号原样写出。第二次汇编标号代真将字符标号用计算出的地址值或偏移量代换。 注伪指令不产生机器码汇编指令与机器指令一一对应。 图7-7 汇编过程的两次扫描 7.7 宏汇编 图7-8 汇编语言指令分类 【预处理含义】 在对程序进行编译之前根据预处理命令对程序作相应处理。经过预处理后编译程序才可以对程序进行编译等处理得到可供执行的目标代码。 编译预处理发生在编译之前。C语言中的以“#”开头的一些预处理指令非常好用可以帮助我们一键修改代码中的参数、控制代码结构等比如宏定义 #define、文件包含 #include、条件编译 #ifdef等。汇编语言中也有类似于 #define的宏定义支持用户自定义的宏指令。宏必须先定义后调用编译前汇编程序会把宏调用展开也就是将宏定义体复制到宏指令位置并使用实参代替虚参然后才进行编译。如上图汇编语言指令分类便可以扩展为三个。宏定义使用 MACRO、ENDM完成具体格式如下 ; 宏定义 macro_name MACRO [哑元表] ; 形参/虚参; 宏定义体 ENDM; 宏调用 macro_name [实元表] ; 实参注编译程序 masm.exe 名称中的“asm”表示汇编语言第一个 “m” 就是 宏(macro)。所以 masm 就意为“宏汇编”。 图7-9 宏展开的示意图 下面给出宏定义和子程序的区别 宏定义编译时会直接进行宏展开。优点是参数传送简单执行效率高缺点是代码占用内存空间大。子程序每次调用都会跳转到相应内存 。优点是模块化省内存缺点是程序开销大。 最后直接给出几个使用“宏定义”简化代码的示例 ;;;;;;;;;;;;;;;;;寄存器压栈;;;;;;;;;;;;;;;;; ; 宏定义 push_reg macropush axpush bcpush cxpush dxpush sipush di endm; 宏调用 push_reg;;;;;;;;;;;;;;;;编写乘法函数;;;;;;;;;;;;;;;; ; 宏定义 multiply macro opr1,opr2,resultpush axpush dxmov ax,opr1imul opr2 ; 有符号数乘法mov result,ax ; 默认舍弃了高16位(dx)的运算结果pop dxpop ax endm; 宏调用 multiply cx,var,xyz[bx];;;;;;;;;;;;;;;;转化成绝对值;;;;;;;;;;;;;;;; ; 宏定义 absolate macro oprlocal next ; 声明为局部标号防止干扰其他程序cmp opr,0jge nextneg opr ; 若为负数求反 next: endm; 宏调用 absolate ax;;;;;;;;;;变元也是操作码的一部分;;;;;;;;; ; 宏定义 leap macro cond,labjcond lab ; 注意看这里的奇妙用法 endm; 宏调用 leap z,there ; 等价于 jz there leap nz,here ; 等价于 jnz here 7.8 宏库 我们可以将宏定义分类放到不同的宏库文件中也就是“宏库”文件后缀为.mac。然后在汇编源程序文件中使用伪指令 include将宏库包含进行即可调用。于是我们显然可以直接调用别人写好的宏库有利于构建汇编生态。 图7-10 创建和调用宏库 7.9 条件汇编 在汇编过程中根据条件把一段源程序包括在汇编语言程序内或者排除在外称之为“条件汇编”。汇编语言中的条件汇编格式为 ifxxx 条件 ... [else] ... endif其中 else可以省略不写并且没有 elseif之类的伪指令。下面给出常见的if伪指令 IF 表达式 ; 表达式不为0则汇编 IFE 表达式 ; 表达式0则汇编IF1 ; 在第一遍扫视期间满足条件 IF2 ; 在第二遍扫视期间满足条件IFDEF 符号 ; 符号已定义则汇编 IFNDEF 符号 ; 符号未定义则汇编IFB 自变量 ; 自变量为空则汇编 IFNB 自变量 ; 自变量不为空则汇编IFIDN 字符串1,字符串2 ; 串1与串2相同 IFDIF 字符串1,字符串2 ; 串1与串2不同图7-11 条件汇编的两个示例 7.10 重复汇编 “重复汇编”用于连续产生完全相同或基本相同的一组代码。本节来介绍三个重复汇编的伪操作REPT、IRP、IRPC本质上都是宏定义。 【重复伪操作REPT】 ; REPT调用格式 REPT 表达式; 重复块 ENDM【代码示例1】将字符’A’到’Z’的ASCII码按顺序填入数组TABLE。 CHAR A TABLE LABEL BYTE ; 重复块 REPT 26DB CHARCHAR CHAR1 ENDM【不定重复伪操作IRP】 ; IRP调用格式 IRP 哑元,自变量表; 重复块 ENDM【代码示例2】生成一组入栈指令。 ; 根据自变量表重复相应次数 IRP REG,AX,BX,CX,DXPUSH REG ENDM; 展开后的等价效果 push ax push bx push cx push dx【不定重复伪操作IRPC】 ; IRPC调用格式 IRPC 哑元,字符串; 重复块 ENDM【代码示例3】生成存储字符串的汇编语句。 ; 根据字符串的字符数量重复操作 array label byte IRPC K, 12345 ; 注意这个字符串不加引号db NO.K ENDM; 实现效果 db NO.1 db NO.2 db NO.3 db NO.4 db NO.57.11 80x86汇编 表7-1 80x86 CPU性能一览 CPU地址总线宽度寻址能力数据总线宽度一次传送数据808016640KB81B8088201MB81B8086201MB162B80286241 6MB162B80386324GB324B 之前一直介绍的是8086汇编本节介绍一下80x86汇编。80x86指的是Intel公司一系列的CPU如上表中CPU性能一览中的系列地址总线宽度由16位晋升到32位到现在已经是64位表中未给出。本节就从下图所给的这六个方面来介绍80386相比于8086所带来的提升。 图7-12 80x86新特性的介绍分类 【80x86的寄存器结构】 80x86的寄存器显而易见的比8086位宽更大、数量更多。如下图左侧的“程序可见寄存器”中粉色表示8086/8088/80286的寄存器绿色则表示80386扩展后的寄存器。可以看到其中“通用寄存器”、“专用寄存器”的位宽展宽加上了Extend前缀“段寄存器”则是新增两个。而下图右侧给出了“专用寄存器”中的“标志寄存器”的扩展细节。如下图所示 图7-13 80x86的寄存器结构扩展 【80x86的寻址方式】 在寻址方式80386兼容之前所有的寻址方式但同时也引入了新的“比例寻址”方便操作更大的元素而不是像8086那样寻址单位只能是一个字节 表7-2 80386寻址寄存器的扩展 地址成分16位寻址808632位寻址80386基址寄存器BX、BP任何32位通用寄存器变址寄存器SI、DI除ESP外的任何32位通用寄存器比例因子11、2、4、8 8086的寻址方式 立即寻址例MOV AX, 3069H。寄存器寻址例MOV AL, BH。直接寻址例MOV AX, [2000H]。寄存器间接寻址例MOV AX, [BX]。寄存器相对寻址例MOV AX, COUNT [SI]。基址变址寻址例MOV AX, [BP][DI]。相对基址变址寻址例MOV AX, MASK [BX][SI]。 80386新增 基址比例变址寻址方式例MOV ECX, [EAX][EDI*4]。相对基址比例变址寻址方式例MOV EAX, TABLE [EBP][EDI*4]。 注对于元素大小为2、4、8字节的数组可以在变址寄存器中给出数组元素的下标依靠比例因子直接将下标转换为变址值。 【80x86的指令系统】 不仅指令集进行了扩展在指令的使用方式上也进行了扩展 指令集的32位扩展 所有16位指令都可扩展到32位比如 MOV EAX,1。可使用32位的存储器寻址方式比如 MOV EAX, [EDX]。 使用方式的扩展 IMUL将 单操作数乘法指令 扩展成 双操作数指令、三操作数指令比如双操作数格式是 IMUL REG, SRC。PUSH允许使用立即数寻址方式比如 PUSH 36H就是对立即数压栈。移位指令移位次数可用8位立即数(1~31)而不再需要cl指示移动位数比如 SHL EAX, 16。 【80x86新增指令】 下面简单列出详细描述可以查找手册。 表7-3 80x86新增指令 新增指令描述新增指令测试类描述MOVSX带符号扩展传送BT位测试MOVZX带零扩展传送BTS位测试并置1PUSHA/PUSHAD所有寄存器进栈BTR位测试并置0POPA/POPAD所有寄存器出栈BTC 位测试并变反LFS/LGS/LSS取地址BSF正向位扫描PUSHFD标志进栈BSR反向位扫描POPFD标志出栈SHLD双精度左移CWDE字转换为双字EAXSHRD双精度右移CDQ双字转换为4字EDX EAXINSB/INSW/INSD串输入BSWAP32位寄存器的字节次序变反OUTSB/OUTSW/OUTSD串输出XADD交换加CMPXCHG比较并交换(486)CMPXCHG8B比较并交换8字节(Pentium)A 【条件设置指令】 之前使用串传送指令时要使用 cld/std指明传送更新的方向下面的“条件设置指令”功能类似也是通过改变相应的标志位设置条件下面简单列出 根据单个条件标志的值把目的字节置 1 SETZ/SETE、SETNZ/SETNESETS/SETNS、SETO/SETNOSETP/SETPE、SETNP/SETPOSETC/SETB/SETNAE、SETNC/SETNB/SETAE 比较两个无符号数根据比较结果把目的字节置 1 SETB/SETNAE/SETC、SETNB/SETAE/SETNCSETBE/SETNA、SETNBE/SETA 比较两个带符号数根据比较结果把目的字节置 1 SETL/SETNGE、SETNL/SETGESETLE/SETNG、SETNLE/SETG 【Intel系列微处理器的3种工作模式】 表7-4 Intel系列微处理器的3种工作模式 工作模式芯片类型工作特点实模式80868086/ 8088支持的单任务工作模式优势在于程序可以直接访问系统内存和硬件设备。实模式现在仍然用于小型的嵌入式设备。保护模式80286程序获得独立的内存段,也会阻止使用自身段范围之外的内存提供对多任务环境的支持。缺点是不兼容上一代的实模式。虚拟8086模式80386以上可以从保护模式切换到实模式提供对原生实模式程序的支持。 注Windows xp及之前的版本都支持MS-DOS实模式但是现代的win8、win10也不再支持实模式因为太久远了。所以前面的DOS开发只能使用纯软件模拟而不能开虚拟机。 最后总结一下上述虽然介绍了很多新特性但是不要觉得学习8086汇编没有用。8086的设计思想仍然是核心熟练掌握8086汇编的原理对于后续扩展到32位、64位的汇编有很大帮助。 7.12 汇编语言集成开发环境 图7-14 与汇编有关的软件环境 之前在开发汇编程序时我们一直使用的是DOS沙盒如上图红色本节按照上图总结一下可以支持汇编语言的开发环境。 DOSBox命令行窗口。 之前按一直在用的命令行的形式有利于理解底层原理。 emu8086图形窗口。 EMU8086集编辑器、汇编器、调试器于一身提供了一个8086CPU的模拟器用窗口形式提供了对8086汇编的支持此外还提供了循序渐进的教程和大量的示例。 下载连接https://emu8086-microprocessor-emulator.en.softonic.com/ 教程软件菜单栏“Help”选项或者 https://yassinebridi.github.io/asm-docs/ masm32 MASM32是一个由个人开发的包含了不同版本工具组建的汇编开发工具包。 MASM32的汇编编译器是MASM6.0以上版本中的Ml.exe资源编译器是Microsoft Visual Studio中的Rc.exe32位链接器是Microsoft Visual Studio中的Link.exe同时包含有其他的一些如Lib.exe和DumpPe.exe等工具。 官网http://www.masm32.com/ visual studio系列 微软自己开发的开发工具下一节介绍。 7.13 用Visual studio开发汇编程序 Microsoft Visual Studio简称VS是微软公司的开发工具包系列产品。VS是一个基本完整的开发工具集它包括了整个软件生命周期中所需要的大部分工具如UML工具、代码管控工具、集成开发环境(IDE)等等。VS支持多种程序设计语言不仅是常见的C/C、Web语言汇编也是支持的 视频“14-用Visual studio开发汇编程序”中演示了如何使用 Visual Studio 2008 创建项目、编译汇编程序、单步调试。 7.14 高级语言的指令级调试 图7-15 汇编语言、机器语言、高级语言的关系 如上图所示“汇编语言”与“机器语言”是一对一关系每一条汇编语言指令对应一条机器语言指令。“高级语言”与“汇编语言”则是一对多关系C语言的一条语句会扩展为多条汇编语言指令或机器指令。 于是根据这样的对应关系显然我们在调试高级语言时也可以直接查看底层的汇编指令。在Visual Studio中创建好Cpp项目后首先需要在“工具”“选项”“调试”下选择“启用地址级调试”然后在调试期间选择“窗口”“反汇编”即可打开反汇编窗口如下图所示。最后给出 图7-16 单步调试-反汇编模式Visual Studio 2022 图7-17 观察x和x在汇编指令中的区别 7.15 反汇编(逆向工程) 图7-18 正向编译和反汇编 和上一小节将高级语言翻译成汇编语言不同反汇编(逆向工程)指的是将机器语言代码转换为汇编语言代码由低级转高级。反汇编常用于软件破解例如找到它是如何注册的从而解出它的注册码或者编写注册机、外挂技术、病毒分析、逆向工程、软件汉化等领域。从正面来说 学习和理解反汇编对软件调试、漏洞分析、OS的内核原理及理解高级语言代码都有相当大的帮助在此过程中我们可以领悟到软件作者的编程思想。总之一句话软件一切神秘的运行机制全在反汇编代码里面。下面给出反汇编的工具 在DOS环境中可以直接使用debug工具中的 u命令会将二进制代码翻译成汇编代码。在Windows环境中可以使用微软开发的 windbg 软件使用方法和上述DOS中的debug工具相同。 7.16 混合编程 图7-19 混合编程示意图 “混合编程”是指使用两种或两种以上的程序设计语言来开发应用程序的过程。之所以使用混合编程是因为程序设计语言有多种它们有各自的优势和不足混合编程可以充分利用各种程序设计语言的优势。如上图所示没有引入混合编程之前每个编程语言只能调用自己的库但是引入混合编程任意语言的主程序都可以调用任意语言的子程序库只要专注于中间的目标程序.obj和程序库.lib能够连接在一起即可。于是混合编程的难点就是不同语言模块之间的接口需要保持一致也就是“编程接口规范”。 最后给出一个C与汇编语言混合编程的一个方案在.cpp文件中使用 __asm标出汇编程序的位置核心的循环功能使用汇编语言完成 【代码示例】将字符串 “abcd” 中的每个字符都转换成大写。 #include iostream using namespace std; int main() {char a[10] abcd;//// 汇编程序起始标志__asm{ ; 初始压栈push ebxpush eaxpush ecx; 循环将小写字符都转换成大写lea ebx, amov ecx, 4tran:mov al,byte ptr [ebx]sub al,20Hmov [ebx], alinc ebxloop tran; 出栈推出pop ecxpop eaxpop ebx}/printf(%s\n,a);getchar();return 0; }7.17 文件结构分析 图7-20 bmp文件格式 BYTE是8bit、UINT是16bit、DWORD是32bit、LONG是64bit。 BMP(Bitmap位图)是Windows操作系统中的标准图像文件格式其格式如上图所示。显然根据上述格式我们可以使用汇编语言、C语言等读取bpm文件的任意信息。下面给出查看图像二进制数据的工具 DOS环境万年不变的Debug工具。使用 debug xxx.bmp将图像加载到内存然后就可以使用 d指令观察图像文件的所有数据了。但显然比较原始。Windows环境Binary Viewer 可以用来查看文件的二进制数据下载连接https://binary-viewer.en.softonic.com/ 当然图像数据格式还有很多比如png、tiff、jpg之类的。当我们对这些格式的二进制文件头了如指掌后是不是直接根据二进制数据就可以反推出图像格式呢唯手熟尔。进一步扩展到其他领域也就掌握了一项根据二进制数据推演文件格式这个非常了不起的技能。 7.18 完结撒花 都不说话是吧看我直接一手手动完结撒花~~
http://www.zqtcl.cn/news/31061/

相关文章:

  • 网站页面字体设置网站html地图导航代码
  • 北京网站建设公司电话汕头站扩建效果图
  • 怎么做合买彩票网站多商户商城小程序源码
  • 网站适合用angular做吗织梦5.5模版安装上去为什么打开网站图片不能显示教程
  • 做谷歌网站wordpress评论区镶嵌图片
  • 西安网站建设西安有哪些网页设计软件
  • 东营市做网站注册企业邮箱收费吗
  • 网站开发工具概述与比较长安东莞网站设计
  • 句容网站设计公司妇产科医生免费咨询
  • 做网站的成本深圳建设花了多少钱
  • 下面不属于网络推广方法江门关键词优化效果
  • 单页面网站推广方法网站开发技术合作协议书
  • 临沂小学网站建设wordpress淘宝客插件
  • 17做网店一样的网站设计网站推荐视频
  • 太原建站服务手机报价大全2021中关村
  • seo网站内容如何查询网站备案信息查询
  • 天津圣辉友联网站建设办公空间设计案例整套
  • 免费pc网站建设友情链接平台站长资源
  • 玉林市网站建设北京网站建设app开发
  • 济南自助建站泉州野外拓展网站建设
  • 永嘉县住房和城乡规划建设局网站襄阳头条新闻
  • 找人做仿网站山东城市建设招生网站
  • 建设部官方网站长春seo公司排名
  • 网站开发实习过程吉林网页制作公司
  • 做网站实际尺寸是多少苏州谷歌seo
  • 帮人做网站在徐州被敲诈五万广州代理记账公司
  • 建设网站建设目的意义wordpress 自己写
  • 贵州政务网站建设规范做蔬菜配送有什么网站可下载了解
  • 手机排行榜2022年宁波seo关键词优化外包
  • 浙江网站建设推荐怎么制作网页教程