汇编语言期末复习

第一章 基本概念

汇编语言是一种助记符的语言,面向开发者。
机器语言是一种纯数字的语言,面向处理器。
汇编语言不是可移植的,具有较强的平台依赖性。

1.1 源码、反码、补码、移码之间的转换

当源码为正数时,源码=反码=补码,移码=补码+127

当源码为负数时,符号位不变其他位取反就为反码,反码+1为补码,移码为将补码符号位取反

补码转化为真值,符号位为0就为其他几位转化为十进制即可

符号位为1就用-128+其他几位转化为十进制就为真值

补码真值=符号位* (-2^N-1)+其余N-1位值

C/C++内嵌汇编中可否定义数据(不行)

设置奇偶标志位依据(低8位)

第二章 x86处理器架构
2.1 操作模式

**保护模式:**处理器的基本模式,所有指令和特性都可用,程序具备独立的内存段,地址线32位,4GB地址空间。
**虚拟8086模式:**处理器可以安全地在多任务系统中执行实地址模式的软件,而不会影响其它运行的程序,地址线20位,1MB地址空间。
**实地址模式:**具有基本x86处理器环境和一些新增的特性,能够直接访问内存和硬件资源,地址线20位,1MB地址空间。
**系统管理模式:**实现电源管理和系统安全等。

2.2 通用寄存器
32位 16位 8位(高) 8位(低)
EAX AX AH AL
EBX BX BH BL
ECX CX CH CL
EDX DX DH DL
32位 16位
ESI SI
EDI DI
EBP BP
ESP SP
2.3 状态标志位

进位标志位(CF),与目标位置相比,无符号算数运算结果太大时,设置该标志位。
溢出标志位(OF),与目标位置相比,有符号算数运算结果太大或太小时,设置该标志位。
符号标志位(SF),算数或逻辑操作产生负结果时,设置该标志位。
零标志位(ZF),算数或逻辑操作产生地结果为零时,设置该标志位。
辅助进位标志位(AC),算数操作在8为操作数中产生了位3向位4的进位时,设置该标志位。
奇偶校验标志位(PF),结果的最低有效字节包函偶数个1时,设置该标志位,否则清除该标志位。一般情况下,如果数据有可能被修改或损坏时,该标志位用于进行错误检测。

第三章 汇编语言基础
3.1 整数常量
标号 说明 标号 说明
h 十六进制 r 编码实数
q/o 八进制 t 十进制(备用)
d 十进制 y 二进制(备用)
b 二进制
3.2 保留字

保留字有特殊意义并且只能在内存中的保存形式为整数字节数值序列。
保留字是没有大小写之分的。
保留字有不同的类型:
1)指令助记符,如MOV、ADD和MUL
2)寄存器名称
3)伪指令,告诉汇编器如何汇编程序。
4)属性,提供变量和操作数的大小与使用信息。
5)运算符,在常量表达式中使用。
6)预定义符号,如@data,它在汇编时返回常量的整数值。

3.3 汇编语言程序模板
.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD

.data;定义变量

.code;代码区
main PROC

INVOKE ExitProcess,0
main ENDP
END main
3.4 内部数据类型
类型 用法
BYTE 8位无符号整数,B代表字节
SBYTE 8位有符号整数,S代表有符号
WORD 16位无符号整数
SWORD 16位有符号整数
DWORD 32位无符号整数,D代表双字
SDWORD 32位有符号整数,SD代表有符号双字
FWORD 48位整数(保护模式中的远指针)
QWORD 64位整数,Q代表四字
TBYTE 80位(10字节)整数,T代表10字节
REAL4 32位(4字节)IEEE短实数
REAL8 64位(8字节)IEEE长实数
REAL10 80位(10字节)IEEE扩展实数
;多初始值
list BYTE 10,20,30,40,50
;定义字符串
list BYTE "GOOD AFTERNOON",0
;DUP操作符
BYTE 20 DUP(0);20个字节,值都为0
3.5 小端顺序

x86处理器在内存中按小端顺序(低到高)存放和检索数据。

第四章 数据传送、寻址和算数运算
4.1 操作数的基本类型

​ 操作数有三种基本类型:
​ 立即数——使用数字文本表达式
​ 寄存器操作数——使用CPU内已命名的寄存器
内存操作数——引用内存位置

4.2 MOV指令

MOV指令的标准格式:(reg为寄存器,mem为内存操作数,imm为立即数)

mov reg,reg
mov reg,mem
mov mem,reg
mov mem,imm
mov reg,imm

目的操作数不能够是imm、CS、EIP和IP(指针寄存器)
操作数不能同为内存操作数

mov eax,val1
mov val2,eax

操作数尺寸必须相同,否则默认转换或语法错
立即数不能直接送段寄存器(16位编程常用段R)

4.3 MOVZX

(零扩展传送,只能用于无符号整数)

val word 9999h
.code
main PROC
mov	eax,12345678h;eax=12345678h
mov ax,val;eax=12349999h
mov	eax,12345678h;eax=12345678h
movzx eax,val;eax=00009999h
4.4 MOVSX

(符号扩展传送,只能用于有符号数)

by byte 10001111b
movsx ax,by;ax=1111111110001111b

十六进制常数最大有效数字大于7,它的最高位就为1

4.5 XCHG

(数据交换指令)

交换数据,实际上是交换数据在容器中的位置
XCHG指令不能使用立即数作为操作数
XCHG指令不能直接交换两个内存操作数
必须使用至少一个寄存器作为临时存储容器

1.以CPU的视角,操作数有哪几种类型?

操作数有3种类型:

1.立即数:使用数字文本表达式

2.寄存器操作数:使用CPU内已命名的寄存器

3.内存操作数:引用内存位置

4.6 INC(增1指令)和DEC(减1指令)

不影响进位标志CF

4.7 ADD/SUB指令

ADD将等长源操作数和目的操作数相加

不改变源操作数

运算结果保存在目的操作数

影响所有标志位

SUB指令的执行实际上是补码与ADD的运算

4.8 NEG指令

操作数转换为其二进制补码,将操作数的符号取反

4.9 与数据相关的运算符和伪指令

OFFSET运算符返回数据标号的偏移量。

ALIGN伪指令将一个变量对齐到字节边界、字边界、双字边界或段落边界。

PTR运算符可以用来重写一个已经被声明过的操作数的大小类型。

TYPE运算符返回变量单个元素的大小,这个大小是以字节为单位计算的。

LENGTHOF运算符计算数组中元素的个数,元素个数是由数组标号同一行出现的数值来定义的。

SIZEOF运算符返回值等于LENGTHOF与TYPE返回值的乘积。

LABLE伪指令可以插入一个标号,并定义它的大小属性,但是不为这个标号分配存储空间。

.data
val16 LABLE WORD
val32 DWORD 12345678h
.code
mov ax,val16;ax=5678h
mov dx,[val16+2];dx=1234h
4.9 寻址方式
4.9.1 直接寻址
var word 123h,456h
mov eax,var+2;变量名+整数常量
mov eax,var[2];变量名[整数常量]
;要定位到数组下一个元素的地址,这里的整数常量为数组元素类型的大小 偏移量不等于C++下标
;word 2个字节 dword 4个字节

.data
sum dword 123h,456h,789h
.code
main PROC
mov eax,sum ;123h
mov eax,sum[4];456h
mov eax,sum+4;456h
mov eax,[sum+4];456h
4.9.2 间接寻址

用寄存器作为指针并控制该寄存器的值。

.data
byteVal BYTE 10h
.code
mov esi,OFFSET byteVal
mov al,[esi];al=10h

;间接寻址操作数组
.data
array DWORD 10000h,20000h,30000h
.code
mov esi,offset array
mov eax,[esi];eax=10000h
add esi,4
mov eax,[esi];eax=20000h
add esi,4
mov eax,[esi];eax=30000h

;变址操作数寻址
.data
array BYTE 10h,20h,30h
.code
mov esi,0
mov al,array[esi];

;变址操作数增加位移量
.data
array WORD 1000h,2000h,3000h
.code
mov esi,OFFSET array
mov ax,[esi]
mov ax,[esi+2]
mov ax,[esi+4]

;变址操作数中的比例因子
.data
array DWORD 100h,200h,300h,400h
.code
mov esi,3*TYPE array
mov eax,array[esi];EAX=400h

mov esi,3
mov eax,array[esi*type array];EAX=400h
4.10 JMP和LOOP指令

JMP指令我无条件跳转到目标地址,该地址用代码标号来标识,并被汇编器转换为偏移量。

LOOP指令正式称为按照ECX计数器循环,将程序块重复特定次数。ECX自动成为计数器,每循环一次计数器值减1。
LOOP指令执行的步骤:
1)ECX减1
2)将ECX与0比较;如果ECX不等于0,则跳转到由目标给出的标号。否则等于零则不跳转,将控制传递到循环后面的指令。

.data
array DWORD 12h,34h,56h
sum DOWRD ?
.code
mov esi,0
mov ecx,lengthof array-1
mov eax,array[esi]
L1:
	inc esi
	add eax,array[esi*TYPE array]
loop L1
	mov sum,eax
jmp L2

L2:
第五章 过程
5.1 PUSH和POP指令

PUSH指令首先减少ESP的值,再将源操作数赋复制到堆栈。

PUSH reg/mem16
PUSH reg/mem32
PUSH imm32

POP指令首先把ESP指向的堆栈元素内容复制到一个16位或32位目的操作数中,再增加ESP的值。

POP reg/mem16
POP reg/mem32

PUSHFD指令把32位EFLAGS寄存器内容压入堆栈,而POPFD指令则把栈顶单元内容弹出到EFLAGS寄存器

PUSHAD指令按照EAX、ECX、EDX、EBX、ESP(执行PUSHAD之前的值)、EBP、ESI和EDI的顺序,将所有32位通用寄存器压入堆栈。
POPAD指令按照相反顺序将同样的寄存器弹出堆栈。

5.2 CALL和RET指令

CALL指令调用一个过程,指挥处理器从新的内存地址开始执行。过程使用RET(从过程返回)指令将处理器转回到该过程被调用的程序点上。CALL指令将其返回地址压入堆栈,再把被调用过程的地址复制到指令指针寄存器。当过程准备返回时,它的RET指令从堆栈把返回地址弹回到指令指针寄存器。

第六章 条件处理
6.1 布尔指令

实质上是位运算指令
CPU状态标志
操作结果等于0时2,零标志位置1.(ZF=1)
操作使得目标操作数的最高位有进位时,进位标志位置1.(CF=1)
符号标志位是目标操作数高位的副本,如果标志位置1,表示是负数;标志位清0,表示是正数。(SF=1/0)
指令产生的结果超出了有符号目的操作数范围时,溢出标志位置1.(OF=1)|
指令使得目标操作数低字节中有偶数个1时,奇偶标志位置1.(PF=1)

6.2 AND指令

需要清零的位为0,保留不变的位为1

6.3 OR指令

需要置1的位为1,保留不变的位为0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qkH6yFja-1624855232869)(C:\Users\BAZINGA\AppData\Roaming\Typora\typora-user-images\image-20210623145206950.png)]

6.4 XOR指令

需要取反的位为1,保留不变的位为0

6.5 NOT指令

将数据所有位取反

6.6 TEST指令

在两个操作数的对应位之间进行AND操作,不修改目标操作数。

6.7 CMP指令

CMP指令执行从目的操作数中减去源操作数的隐含减法操作,并且不修改操作数

无符号数CMP结果 ZF CF
目的操作数<源操作数 0 1
目的操作数>源操作数 0 0
目的操作数=源操作数 1 0
有符号数CMP结果 标志位
目的操作数<源操作数 SF≠OF
目的操作数>源操作数 SF=OF
目的操作数=源操作数 ZF=1
6.8 置位和清除单个CPU标志位
;零标志位
test al,0;ZF=1
and al,0;ZF=1
or al,1;ZF=0
;符号标志位
;若要符号标志位置1,将操作数的最高位和1进行OR操作
;若要清除符号标志位,将操作数最高位和0进行AND操作
or al,80h;SF=1 80h=10000000
or al,7Fh;SF=0 7Fh=01111111
;进位标志
stc ;CF=1
clc ;CF=0
;溢出标志位
;将两个正数相加结果超出寄存器表示范围,OF被置为1
;清除溢出标志位,将操作数和0进行OR操作
mov al,7Fh ;AL=+127
inc al	;AL=80h(-128),OF=1 -1(11111111)倒着来的
or eax,0	;OF=0
6.9 条件跳转指令
6.9.1 基于特定标志位值的跳转
助记符 说明 标志位/寄存器
JZ(Jump if Zero) 为零跳转 ZF=1
JNZ(Jump if Not Zero) 非零跳转 ZF=0
JC 进位跳转 CF=1
JNC 无进位跳转 CF=0
JO 溢出跳转 OF=1
JNO 无溢出跳转 OF=0
JS 有符号跳转 SF=1
JNS 无符号跳转 SF=0
JP 偶校验跳转 PF=1
JNP 奇校验跳转 PF=0
6.9.2 基于相等性的跳转

CMP leftOp,rightOp

助记符 说明
JE 相等跳转(leftOp==rightOp)
JNE 不相等跳转(leftOp!=rightOp)
JCXZ CX=0跳转
JECXZ ECX=0跳转
JRCXZ RCX=0跳转(64位模式)
6.9.3 基于无符号数比较的跳转
助记符 说明
JA 大于跳转(leftOp>rightOp)
JNBE 不小于或等于跳转(与JA相同)
JAE 大于或等于跳转(若leftOp≥rightOp)
JNB 不小于跳转(与JAE相同)
JB 小于跳转(若leftOp
JNAE 不大于或等于跳转(与JB相同)
JBE 小于或等于跳转(leftOp≤rightOp)
JNA 不大于跳转(与JBE相同)
6.9.4 基于有符号数比较的跳转
助记符 说明
JG 大于跳转(leftOp>rightOp)
JNLE 不小于或等于跳转(与JG相同)
JGE 大于或等于跳转(若leftOp≥rightOp)
JNL 不小于跳转(与JGE相同)
JL 小于跳转(若leftOp
JNGE 不大于或等于跳转(与JL相同)
JLE 小于或等于跳转(leftOp≤rightOp)
JNG 不大于跳转(与JLE相同)

JMP转移范围32位,LOOP、条件转移范围8位

6.9.5 条件循环指令

LOOPZ(ZF=1跳转,零标志位置1跳转)

LOOPE(相等跳转)

LOOPZ和LOOPE不影响任何标志位

32位模式下ECX是循环计数器,64位模式下RCX是循环计数器

LOOPNZ(非0跳转,ZF=0)

LOOPNE(不等跳转)

第七章 整数运算
7.1 移位和循环移位指令
SHL(Shift Logic Left) 左移 ROR 循环右移
SHR(Shift Logic Right) 右移 RCL 带进位的循环左移
SAL(Shift Arithmetic Left) 算数左移 RCR 带进位的循环右移
SAR(Shift Arithmetic Right) 算数右移 SHLD 双精度左移
ROL 循环左移 SHRD 双精度右移

逻辑移位:空出来的位用0填充,移出去的放在CF标志位中

位元乘法:任何操作数左移n位,即将该数乘以2^n(SHL)

位元除法:将一个无符号数右移n位,即将该数除以2^n(SHR)

SAL算术左移操作,最低位以0填充,最高位传送到CF中同SHL

SAR算数右移操作,最高位以自身填充,最低位传送到CF中

有符号数除法:使用SAR指令就可以将有符号操作数除以2的幂

ROL循环左移,最高位复制到进位标志位和最低位。

ROR循环右移,最低位复制到进位标志位和最高位。

RCL带进位循环左移,CF传送到最低位,最高位传送到CF

RCR带进位循环右移,CF传送到最高位,最低位传送到CF

SHLD双精度左移,将目的操作数向左移动指定位数。移动形成的空位由源操作数的高位填充。源操作数不变,符号标志位、零标志位、辅助进位标志位、奇偶标志位和进位标志位会受影响。

SHRD同SHLD只是方向不同。

shld dest,source,count

关于移位指令的移位次数用8位立即数表示

7.2 乘法指令
7.2.1 MUL无符号数乘法指令
MUL
reg mem8
reg mem16
reg mem32

8位、16位或32位被乘数分别为AL、AX或EAX中

被乘数 乘数 乘积
AL reg/mem8 AX
AX reg/mem16 DX:AX
EAX reg/mem32 EDX:EAX

高半部分如果不为0则CF位置位CF=1

高半部分等于0则CF被清除CF=0

7.2.2 IMUL有符号数乘法指令

IMUL有单操作数、双操作数和三操作数三种格式

将乘积低半部分的最高位符号扩展到高半部分

如果高半部分不是低半部分的符号位扩展则OF=1
OF=1为正数否则为负数

二操作数和三操作数中会根据目的操作数也就是第一个操作数对乘积进行截取,如果有效位被截取掉了,溢出标志位和进位标志位置1

7.3 除法指令
7.3.1 DIV无符号数除法指令
被除数 除数 余数
AX reg/mem8 AL AH
DX:AX reg/mem16 AX DX
EDX:EAX reg/mem32 EAX EDX
7.3.2 IDIV有符号数除法指令
被除数 除数 余数 符号扩展
AX reg/mem8 AL AH CBW
DX:AX reg/mem16 AX DX CWD
EDX:EAX reg/mem32 EAX EDX CDQ
7.4 加法扩展
7.4.1 ADC指令

ADC指令将源操作数和进位标志位的值都与目的操作数相加。

ADC reg,reg
ADC mem,reg
ADC reg,mem
ADC mem,imm
ADC reg,imm

dl:al

edx:eax

7.4.2 SBB指令

SBB指令从目的操作数中减去源操作数和进位标志位的值。

初始化:加数和被加数起始地址送地址寄存器、循环次数送ECX、CLC

循环体:用ADC将被加数当前部分与加数当前部分相加,存部分和;修改被加数和加数地址寄存器,如用ADD修改要保护/恢复状态标志寄存器;LOOP构成循环

善后:用一条ADC指令保存最高部分加法操作的进位

stc指令将CF置1

第8章 高级过程
8.1 局部变量

局部变量再堆栈上运行,汇编时不确定初始值但是在运行时进行初始化。
LOCAL伪指令
LOCAL 变量列表
LOCAL 标号:类型[,标号:列表][,标号:列表]
LOCAL temp:DWORD,Flags:BYTE
LOCAL伪指令定义的变量列表需要占用堆栈空间,要保证堆栈中有足够的空间供局部变量使用。
如果要使用LOCAL伪指令,它必须紧跟在PROC伪指令的后面。

LOCAL varlist;varlist为变量定义列表,用逗号分隔表项,可选为跨越多行
MySub PROC
	LOCAL val1:BYTE
BubbleSort PROC
	LOCAL temp:DWORD,SwapFlag:BYTE,pArray:PTR WORD,TempArray[10]:DWORD

8.2 堆栈帧

堆栈帧是一块堆栈保留区域,用于存放被传递的实际参数、子程序的返回值、局部变量以及被保存的寄存器。
堆栈帧的创建步骤:
1)被传递的实际参数。如果有,则压入堆栈;
2)当子程序被调用时,使该子程序的返回值压入堆栈;
3)子程序开始执行时,EBP被压入堆栈;
4)设置EBP等于ESP。从这时开始,EBP就变成了该子程序所有参数的引用地址;
5)如果有局部变量,修改ESP以便在堆栈中为这些变量预留空间;
6)如果需要保存寄存器,就将它们压入堆栈。

8.3 传递参数
;值传递
.data
val1 DWORD 5
val2 DWORD 6
.code
push val1
push val2
call AddTwo
;引用传递
.code
push offset val1
push offset val2
call swap
;传递数组
.data
array DWORD 50 dup(?)
.code
push offset array
call ArrayFill
8.4 访问堆栈参数
8.5 LEA指令

LEA指令返回简介操作数的地址。

lea esi,[ebp-30]
8.6 递归

递归是直接或者间接调用自身子过程

;二维数组寻址
mov esi,rowsize
mov edi,index_collum
table[esi+edi*type table]

先入栈的地址大,后入栈的地址小

8.7 ENTER和LEAVE指令

ENTER指令为被调用过程自动创建堆栈帧。它为局部变量保留堆栈空间,把EBP入栈。
1)把EBP入栈;
2)把EBP设置为堆栈帧的基址(mov ebp,esp)
3)为局部变量保留空间(sub esp,numbytes)

ENTER numbytes,nestinglevel;numbytes为4的倍数,nestinglevel为主调过程堆栈帧赋值到当前帧的堆栈帧指针的个数,一般为0
Mysub PROC
	enter 8,0
;等效于
Mysub PROC
	push ebp
	mov ebp,esp
	sub esp,8

LEAVE指令结束一个过程的堆栈帧,它反转了ENTER指令的操作

MySub PROC
	enter 8,0
	.
	.
	leave
	ret
MySub ENDP
;等效于
MySub PROC
	push ebp
	mov ebp,esp
	sub esp,8
	.
	.
	mov esp,ebp
	pop ebp
	ret
MySub ENDP

ENTER和LEAVE指令最好搭配使用否则容易出错

8.8 INVOKE、ADDR、PROC、PROTO
8.8.1 INVOKE伪指令

将参数入栈并调用过程,INVOKE是CALL一个方便的替代品。

INVOKE procedureName [,argumentList];procedureName为调用的子程序名,argumentList为参数列表

INVOKE DumpArray,OFFSET array,LENGTHOF array,TYPE array
;等效于
push TYPE array
push LENGTHOF array
push OFFSET array
call DumpArray
8.8.2 ADDR运算符

使用INVOKE调用过程时,它可以传递指针参数。

INVOKE FillArray,ADDR myArray;传递myArray指针

.data
Array DWORD 20 DUP(?)
.code
...
INVOKE Swap,
	ADDR Array,
	ADDR [Array+4]
;等效于
push offset Array+4
push offset Array
call Swap
8.8.3 PROC伪指令
lable PROC [attributes] [USES reglist], parameter_list;lable是用户自定义的标号,parameter_list是参数列表
;PROC在这里的作用就是函数的定义,有了参数列表就可以直接用名字来引用参数而不是计算堆栈偏移量

AddTwo PROC,
	val1:DWORD,
	val2:DWORD
	mov eax,val1
	add eax,val2
	ret
Addtwo ENDP
;等效于
AddTwo PROC
	enter 0,0
	mov eax,dword ptr [ebp+8]
	add eax,dword ptr [ebp+0CH]
	leave
	ret 8
AddTwo ENDP

由PROC修改的RET指令 当PROC有一个或多个参数时,ret指令中的常数是参数个数乘以4
在PROC 后面使用USES指令

ArraySum PROC USES esi,ecx
	ret
ArraySum ENDP
;等效于
push esi
push ecx
pop ecx
pop esi
ret
8.8.4 PROTO伪指令

PROTO就是用来声明函数原型的伪指令

MySub PROTO;过程原型
	.
INVOKE MySub;过程调用
	.
MySub PROC;过程实现
	.
	.
MySub ENDP
第9章 字符串和数组
9.1 基本的字符串操作指令

(ESI为源操作数,EDI为目的操作数,都为隐含操作数)

指令 说明
MOVSB、MOVSW、MOVSD 传送字符串数据,将由ESI寻址的内存地址处的数据复制到EDI寻址的内存地址处
CMPSB、CMPSW、CMPSD 比较字符串,比较由ESI和EDI寻址的两个内存地址处的值
SCASB、SCASW、SCASD 扫描字符串,比较累加器(AL、AX、EAX)与EDI寻址的内存地址处的内容
STOSB、STOSW、STOSD 保存字符串数据,存储累加器的内容至EDI寻址的内存地址处
LODSB、LODSW、LODSD 从字符串加载到累加器,加载ESI寻址的内存地址处的数据至累加器
9.2 重复前缀

[每次ECX-1,ESI及EDI每次增加/减少B/W/D(1/2/4个字节)]

指令 说明
REP ECX>0重复
REPZ、REPE ECX>0且零标志位置1(ZF=1)重复
REPNZ、REPNE ECX>0且零标志位清0(ZF=0)重复
;将str1中传送10个字节到str2
cld
mov esi,offset str1
mov edi,offset str2
mov ecx,10
rep movsb

CLD:清除方向标志位,也就是正向,ESI和EDI增加
STD:设置方向标志位,也就是反向,ESI和EDI减小

9.3 串操作指令(特点)

源串指针为ESI,目的串指针为EDI
操作次数(串长度)在ECX中
指针与计数器自动修改
加减由DF确定:CLD、STD
修改长度 B=BYTE、W=WORD、D=DWORD
重复前缀有REP、REPE/REPZ、REPNE/REPNZ
允许源和目的操作数都是存储单元

执行串操作之前,应先设置:
(1)源串首地址(末地址)->ESI
(2)目的串首地址(末地址)->EDI
(3)串长度->ECX
(4)建立方向标志(CLD或STD)
执行串操作指令后,ESI和EDI已经越界或超过目标

9.4 MOV系指令程序过程

MOVSB、MOVSW和MOVSD
B:BYTE、W:WORD、D:DWORD
指令会自动修改ESI和EDI的值
自动设置增加还是减少,以及增减数值的多少
连续的字符串移动指令使用方法
设置ESI和EDI的方向:增加或者减少

设置ECX寄存器内容为要复制的字符串的数量
设置源字符串偏移ESI和目的字符串偏移EDI两个寄存器
使用重复前缀指令rep设置重复执行的指令(三条指令之一)
rep的使用类似于loop,会按照ECX的值重复执行指令

;复制20个DWORD到另外一个数组
.data
val1 DWORD 20 dup(OFFFFFFFFh)
val2 DWORD 20 dup(?)
.code
cld
mov esi,offset val1
mov edi,offset val2
mov ecx,lengthof val1
rep movsd
9.5 CMP系指令程序过程

CMPSB、CMPSW和CMPSD
三条指令隐含操作为用左边操作数减去右边操作数,进而用户可以用无符号数跳转指令进行跳转

;单个比较
.data
val1 DWORD 1234h
val2 DWORD 5678h
.code
mov esi,offset val1
mov edi,offset val2
cmpsd;比较双字
ja L1;val1>val2跳转
;数组比较
.data
val1 WORD 12h,34h,56h
val1 WORD 12h,34h,78h
.code
mov esi,offset val1
mov edi,offset val2
cld
mov ecx,lengthof val
repe cmpsd;相等重复
9.6 SCA系指令程序过程

SCASB、SCASW和SCASD
分别将AL、AX或EAX中的值同EDI寻址的目标内存中的字节、字或者双字比较
特别适用于在长字符串或数组中查找匹配

;在字符串中查找字符
.data
val1 byte "abcdefgh",0
.code
mov edi,offset val1
mov ecx,lenthof val
cld
mov al,"f"
repne scasb;不相等重复,ZF=0
jnz quit;ZF=0退出,即没找到
dec edi;edi-1指向字符串中字符
9.7 STO系指令程序过程

STOSB、STOSW和STOSD
分别将AL、AX或EAX中值存储到EDI寻址的目标内存单元中
特别适用于填充字符串或者数组

.data
count=100
val DWORD count dup(?)
.code
mov edi,offset val
mov al,0FFh
mov ecx,count
cld
rep stosw;用AL值进行填充
9.8 LOD系指令程序过程

LODSB、LODSW和LODSD
从ESI寻址的内存单元中将对应尺寸的内容复制到AL、AX或者EAX寄存器中

;把一个双字数组中的每个元素都乘以同一个常数
INCLUDE Irvine32.inc
.data
val DWORD 1,2,3,4,5,6,7,8,9,.10
multip DWORD 10
.code
cld;正向
mov esi,offset val;原数组
mov edi,esi;将目标数组设为原数组
mov ecx,lengthof val;循环次数
L1:
lodsd;将数组中的元素加载到EAX
mul multip;乘以乘数
stosd;将EAX中的数传回数组
loop L1
exit
main ENDP
END main
9.9 复习

1.参照字符串原语,哪个32为寄存器被称为累加器?
EAX

2.哪条指令比较累加器中的32位整数与由EDI指向的内存数值?
SCASD

3.STOSD指令使用哪个变址寄存器?
EAX

4.哪条指令将数值从ESI指向的内存地址复制到AX?
LODSW

5.对CMPSB指令来说,REPZ前缀的作用是什么?
当源操作数地址(ESI)和目的操作数(EDI)指向地址的值相等时重复

你可能感兴趣的:(汇编语言)