汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言.在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数的地址.在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令,普遍地说,特定的汇编语言和特定的机器语言指令集是相互对应的,不同平台之间不可直接移植.

字串操作指令

移动串指令: MOVSB、MOVSW、MOVSD ;从 ESI -> EDI; 执行后, ESI 与 EDI 的地址移动相应的单位

比较串指令: CMPSB、CMPSW、CMPSD ;比较 ESI、EDI; 执行后, ESI 与 EDI 的地址移动相应的单位

扫描串指令: SCASB、SCASW、SCASD ;依据 AL/AX/EAX 中的数据扫描 EDI 指向的数据, 执行后 EDI 自动变化

储存串指令: STOSB、STOSW、STOSD ;将 AL/AX/EAX 中的数据储存到 EDI 给出的地址, 执行后 EDI 自动变化

载入串指令: LODSB、LODSW、LODSD ;将 ESI 指向的数据载入到 AL/AX/EAX, 执行后 ESI 自动变化

其中的 B、W、D 分别指 Byte、Word、DWord, 表示每次操作的数据的大小单位.

上述指令可以有重复前缀:

REP ECX > 0 时

REPE (或 REPZ) ECX > 0 且 ZF=1 时

REPNE(或 REPNZ) ECX > 0 且 ZF=0 时

;重复前缀可以自动按单位(1、2、4)递减 ECX

字符串复制(movsb):

.data
string1 db "hello lyshark",0 ; 原始字符串
str_len equ $ - string1 -1 ; 计算出原始字符串长度
string2 db str_len dup(?),0 ; 目标内存地址 .code
main PROC
cld ; 清除方向标志
mov esi,offset string1 ; 取源字符串内存地址
mov edi,offset string2 ; 取目标字符串内存地址
mov ecx,str_len ; 指定循环次数,为原字符串长度
rep movsb ; 逐字节复制,直到ecx=0为止
ret
main ENDP
END main

另一种字串复制(movsb): 不使用rep重复前缀的方式完成字串复制.

.data
string1 db "hello lyshark",0 ; 原始字符串
str_len equ $ - string1 -1 ; 计算出原始字符串长度
string2 db str_len dup(?),0 ; 目标内存地址 .code
main PROC
lea esi,string1 ; 取string1的地址
lea edi,string2 ; 取string2的地址
mov ecx,str_len ; 取字符串长度,用于循环
cld ; 方向->正向
@@: movsb ; 每次复制一个字节BYTE
dec ecx ; 每次ecx减一
jnz @B ; 如果ecx不为0则循环
ret
main ENDP
END main

(movsd)四字节复制字串:

.data
ddSource DWORD 10h,20h,30h ; 定义三个四字节数据
ddDest DWORD lengthof ddSource dup(?) ; 得到目标地址 .code
main PROC
lea esi,ddSource
lea edi,ddDest
mov ecx,lengthof ddSource
cld
rep movsd
ret
main ENDP
END main

CMPSB:

.data
Text1 db "hello lyshark",0
Text2 db "hello lyshar1",0
.code
main PROC
lea esi,Text1
lea edi,Text2
mov ecx,lengthof Text1
cld
repe cmpsb
je L1
xor eax,eax ; 字串不同则清空eax
jmp L2
L1: xor ebx,ebx ; 字串相同则清空ebx
L2: ret
main ENDP
END main

CMPSD: 比对两个双字数据是否相等.

.data
var1 DWORD 1234h
var2 DWORD 5678h
.code
main PROC
lea esi,var1
lea edi,var2
cmpsd
je L1
xor eax,eax ; 两数如果相等则清空eax
jmp L2
L1: xor ebx,ebx ; 两数不相等则清空ebx
L2: ret
main ENDP
END main

CMPSW:

.data
Array1 WORD 1,2,3,4,5 ; 必须全部相等才会清空ebx
Array2 WORD 1,3,5,7,9
.code
main PROC
lea esi,Array1
lea edi,Array2
mov ecx,lengthof Array1 cld
repe cmpsw
je L1
xor eax,eax ; 两数不相等则清空eax
jmp L2
L1: xor ebx,ebx ; 两数相等则清空ebx
L2: ret
main ENDP
END main

SCASB 扫描字串: 依据 AL/AX/EAX 中的数据扫描 EDI 指向的数据, 执行后 EDI 自动变化

.data
szText BYTE "ABCDEFGHIJK",0
.code
main PROC lea edi,szText
mov al,"F"
mov ecx,lengthof szText -1
cld
repne scasb ; 如果不相等则重复
je L1
xor eax,eax ; 如果没找到F则清空eax
jmp L2
L1: sub ecx,lengthof szText -1
neg ecx ; 如果找得到, 这里显示是第几个字符; 本例结果是 6
L2: ret
main ENDP
END main

STOSB 存储字串: 将 AL/AX/EAX 中的数据储存到 EDI 给出的地址, 执行后 EDI 自动变化

.data
len = 10
szText db len dup(0),0
.code
main PROC
lea edi,szText ; EDI指向字符串
mov al,"W" ; 定义查找字母为W
mov ecx,len ; 设置查找计数器
cld ; 方向=正向
rep stosb ; ecx>0则执行
ret
main ENDP
END main

LODSW 载入指令: 将 ESI 指向的数据载入到 AL/AX/EAX, 执行后 ESI 自动变化,如下是累加求和

.data
Array WORD 1,2,3,4,5,6,7,8,9,10
.code
main PROC
lea esi,Array
mov ecx,lengthof Array
xor edx,edx
xor eax,eax
@@: lodsw
add edx,eax
loop @B mov eax,edx ; 最后将相加结果放入eax main ENDP
END main

初始化内存: 把String字符串中的,每一个字节均填充初始化为0FFh

.data
Count = 100 ; 申请空间为100
String BYTE Count DUP(?) ; 初始化为BYTE
.code
main PROC
mov al,0FFh ; 指定要填充的数据为0FFh
mov edi,offset String ; EDI寄存器指向目标内存
mov ecx,Count ; 循环计数
cld ; 初始化:方向=前方
rep stosb ; 以AL中的值进行填充
ret
main ENDP
END main

数组的乘法: 把双字数组中的每一个元素分别乘以一个常量,程序中使用了(LODSD加载),(STOSD保存).

.data
Array DWORD 1,2,3,4,5
Multi DWORD 10
.code
main PROC
mov esi,offset Array ; 源指针
mov edi,esi ; 目的指针 cld ; 方向=向前
mov ecx,lengthof Array ; 循环计数器
L1: lodsd ; 加载[esi]至EAX
mul Multi ; 将EAX乘以10
stosd ; 将结果从EAX存储至[EDI]
loop L1
ret
main ENDP
END main

计算字符串长度: 以下代码用于计算字符串的长度,并将结果保存在EAX寄存器中.

.data
String BYTE "hello world",0 ; 带计算字符串
.code
main PROC
mov edi,offset String ; 取出字符串的基地址
xor eax,eax ; 清空eax用作计数器 L1: cmp byte ptr [edi],0 ; 分别那[edi]的值和0作比较
je L2 ; 上一步为零则跳转得到ret
inc edi ; 否则继续执行
inc eax
jmp L1
L2: ret main ENDP
END main

小写字串转大写: 将MyString变量中的小写字符串,依次转换为大写字符串.

.data
MyString db "hello lyshark",0 ; 定义MyString字符串 .code
main PROC
mov esi,offset MyString ; 取出字符串的偏移地址
L1: cmp byte ptr [esi],0 ; 分别拿出每一个字节,与0比较
je L2 ; 如果相等则跳转到L2
and byte ptr [esi],11011111b ; 执行按位与操作
inc esi ; 每次esi指针递增1
jmp L1 ; 重复循环
L2: ret
main ENDP
END main

定义二维数组: 定义一个二维数组Table,并取出第一行中的第2偏移地址的元素.

.data
Table WORD 10h,20h,30h,40h,50h ; 定义一个数组
Row = ($ - Table) ; 取出数组每行的字节数
WORD 60h,70h,80h,90h,0Ah ; 继续定义数组
.code
main PROC
row_index = 1 ; 表的偏移地址
column_index = 2 ; 行的偏移地址 mov ebx,offset Table ; 取偏移地址给ebx
add ebx,Row*row_index ; 每行元素*偏移 mov esi,column_index ; 将行偏移赋值给esi
mov ax,[ebx+esi*TYPE Table] ; Table比例因子只能是2,4,8
main ENDP
END main

## 位操作指令

符号扩展(CBW/CWDE):

.code
main PROC
mov al,7fh
cbw ; 将 AL 扩展为 AX
PrintHex ax ;007F
mov al,80h
cbw
PrintHex ax ;FF80 mov ax,7fffh
cwde ; 将 AX 扩展为 EAX
PrintHex eax
main ENDP
END main

符号扩展(CDQ/CWD):

.code
main PROC
mov eax,7FFFFFFFh
cdq ; 将 EAX 扩展为 64 位数 EDX:EAX
PrintHex edx ;00000000
PrintHex eax ;7FFFFFFF mov ax, 7FFFh
cwd ; 将 AX 扩展为 DX:AX
PrintHex dx ;0000
PrintHex ax ;7FFF main ENDP
END main

BT、BTS、BTR、BTC: 位测试指令

;BT(Bit Test): 位测试

;BTS(Bit Test and Set): 位测试并置位

;BTR(Bit Test and Reset): 位测试并复位

;BTC(Bit Test and Complement): 位测试并取反

;它们的结果影响 CF

;它们的指令格式相同:

BT r16/r32/m16/m32, r16/r32/m16/m32

BT r16/r32/m16/m32, i8

.code
main proc
;BT 把 10000001b 的第七位复制到 CF, 得知是 1
mov dx, 10000001b
bt dx, 7
lahf
PrintHex ah ;47 - 01000111b (CF=1)
;BT 把 10000001b 的第六位复制到 CF, 得知是 0
bt dx, 6
lahf
PrintHex ah ;86 - 10000110b (CF=0) ;BTS 在执行 BT 命令的同时, 把操作数的指定位置为 1
mov dx, 10000001b
bts dx, 6
PrintHex dl ;C1 - 11000001b ;BTR 在执行 BT 命令的同时, 把操作数的指定位置为 0
mov dx, 10000001b
btr dx, 7
PrintHex dl ;01 - 00000001b ;BTC 在执行 BT 命令的同时, 把操作数的指定位取反
mov dx, 10000001b
btc dx, 0
PrintHex dl ;80 - 10000000b
btc dx, 0
PrintHex dl ;81 - 10000001b
ret
main endp
end main

BSF、BSR: 位扫描指令

;BSF(Bit Scan Forward): 位扫描, 低 -> 高

;BSR(Bit Scan Reverse): 位扫描, 高 -> 低

;它们的结果影响 ZF

;扫描的是参数二, 找到是 1 的位后, 把位置数给参数一并置 ZF=0

;找不到(也就是参数二是 0)时, 置 ZF=1

;它们的指令格式相同:

BSF r16/r32, r16/r32/m16/m32

.code
main proc
;扫描到时
mov dx, 0000111100001100b
bsf cx, dx
PrintDec cx ;2 - 也就是左数第 3 位 bsr cx, dx
PrintDec cx ;11 - 也就是左数第 12 位 ;扫描不到时
mov cx, 0FFFFh
mov dx, 0
bsf cx, dx
lahf
PrintHex ah ;C6 - 11000110 (ZF=1)
PrintHex cx ;FFFF - 找不到时不会影响到目的值
ret
main endp
end main

其他测试指令

参考文献:《Intel 汇编语言程序设计》,《琢石成器-Win32汇编语言程序设计》,《汇编语言-王爽》

Win32汇编之其他指令的更多相关文章

  1. Win32汇编常用算数指令

    汇编语言(assembly language)是一种用于电子计算机.微处理器.微控制器或其他可编程器件的低级语言,亦称为符号语言.在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地 ...

  2. 学 Win32 汇编[21] - 传送指令: MOV、LEA、XCHG、XLATB、XLAT、MOVZX、MOVSX

    汇编指令的一般性要求: 1.两个操作数的尺寸必须一致; 2.操作数不能同为内存. MOV(Move): 最常用的数据传送指令 ;该指令不影响 EFlags ;指令格式: (其中的 r.m.i 分别表示 ...

  3. Win32汇编环境配置

    放假了,发现自己知识面窄,趁有时间就打算折腾下Win32汇编.其实在学校也上过汇编课,是基于dos的.那时老师不务正业,老跟我们讲政治经济文化,唯独不怎么讲课;再加上自己的问题,导致了dos汇编学得好 ...

  4. Win32汇编学习(1):基本概念

    背景知识 Windows 把每一个 Win32 应用程序放到分开的虚拟地址空间中去运行,也就是说每一个应用程序都拥有其相互独立的 4GB 地址空间,当然这倒不是说它们都拥有 4GB 的物理地址空间,而 ...

  5. 罗云彬win32汇编教程笔记 子函数的声明, 定义与调用

    在主程序中用call指令来调用子程序. Win32汇编中的子程序也采用堆栈来传递参数,这样就可以用invoke伪指令来进行调用和语法检查工作. 一. 子程序的定义 子程序的定义方式如下所示. 子程序名 ...

  6. 8086汇编和Win32汇编

    8086汇编是指在某环境下汇编编译产生的程序,用机器去执行每条指令的长度为16位(可小于16),如DOS操作系统:WIN32汇编是32位环境下的汇编,如Windows(Windows也有64位的,XP ...

  7. win32汇编基础

    win32汇编基础知识 Debug 版本|Release 版本 Debug 是"调试"的意思,Debug 版本就是为调试而生的,编译器在生成 Debug 版本的程序时会加入调试辅助 ...

  8. Win32汇编开始 Hello Asm

    今天开始学习Win32汇编 因为自己很多都是Windows方面 所以 接触一下Win32汇编 . ;.386指令集 .model flat,stdcall ;工作模式 option casemap:n ...

  9. Win32汇编学习(5):绘制文本2

    这次我们将学习有关文本的诸多属性如字体和颜色等. 理论: Windows 的颜色系统是用RGB值来表示的,R 代表红色,G 代表绿色,B 代表蓝色.如果您想指定一种颜色就必须给该颜色赋相关的 RGB ...

随机推荐

  1. 使用python播放音乐

    1.首先安装pygame,pip install pygame 2.上代码: import time import pygame #音乐路径 filepath=r"C:\Users\1473 ...

  2. Mongodb内存管理和使用情况查询

    overview MongoDB使用的是内存映射存储引擎,即Memory Mapped Storage Engine,简称MMAP.MMAP可以把磁盘文件的一部分或全部内容直接映射到内存,这样文件中的 ...

  3. redis 数据类型详解 以及 redis适用场景场合(滴滴)

    滴滴的面试官问了个问题关于redis的: 我现在想服务器每分钟接收一个用户的请求小于60个,如何处理: 答:使用Redis 缓存服务器,可以设置key=用户ID value不停地加一到了60就停止,然 ...

  4. openwrt系统源码地址

    https://dev.openwrt.org/wiki/GetSource http://www.openwrtdl.com/wordpress/openwrt-full-tutorial

  5. Qt Model/View 的简单说明

    目录: (一) Qt Model/View 的简单说明 .预定义模型 (二)使用预定义模型 QstringListModel例子 (三)使用预定义模型QDirModel的例子 (四)Qt实现自定义模型 ...

  6. ELMO及前期工作 and Transformer及相关论文

    论文1 https://arxiv.org/pdf/1705.00108.pdf Semi-supervised sequence tagging with bidirectional languag ...

  7. 1.ibatis核心类

  8. 深度学习之加载VGG19模型分类识别

    主要参考博客: https://blog.csdn.net/u011046017/article/details/80672597#%E8%AE%AD%E7%BB%83%E4%BB%A3%E7%A0% ...

  9. openstack部署glance

    一.建立glance数据库并且给权限设置第三方登录 mysql -uroot -p0330 CREATE DATABASE glance; GRANT ALL PRIVILEGES ON glance ...

  10. Redis 部署安装

    一.Redis介绍 Redis是当前比较热门的NOSQL系统之一,它是一个key-value存储系统.和Memcache类似,但很大程度补偿了Memcache的不足,它支持存储的value类型相对更多 ...