上一节: 汇编语言 数字
上一节
下一节: 汇编语言 数组
下一节
汇编语言 字符串
字符串
在前面的示例中,我们已经使用了可变长度的字符串。可变长度字符串可以根据需要包含任意多个字符。通常,我们通过以下两种方式之一指定字符串的长度:
显式存储字符串长度
使用哨兵字符
我们可以使用表示位置计数器当前值的$位置计数器符号来显式存储字符串长度。在以下示例中-
msg db 'Hello, world!',0xa ;我们常见的字符
len equ $ - msg ;长度
$指向字符串变量msg的最后一个字符之后的字节。因此,$ - msg给出字符串的长度。我们也可以写
msg db 'Hello, world!',0xa ;our dear string
len equ 13 ;length of our dear string
另外,您可以存储带有尾部定点字符的字符串来定界字符串,而不是显式存储字符串长度。前哨字符应为不出现在字符串中的特殊字符。
例如-
message DB 'I am loving it!', 0
字符串指令
每个字符串指令可能需要一个源操作数,一个目标操作数或两者。对于32位段,字符串指令使用ESI和EDI寄存器分别指向源和目标操作数。但是,对于16位段,SI和DI寄存器分别用于指向源和目标。
有五个用于处理字符串的基本说明。他们是-
MOVS-该指令将1字节,字或双字数据从存储位置移到另一个位置。
LODS-该指令从存储器加载。如果操作数是一个字节,则将其加载到AL寄存器中;如果操作数是一个字,则将其加载到AX寄存器中,并将双字加载到EAX寄存器中。
STOS-该指令将数据从寄存器(AL,AX或EAX)存储到存储器。
CMPS-该指令比较内存中的两个数据项。数据可以是字节大小,字或双字。
SCAS-该指令将寄存器(AL,AX或EAX)的内容与内存中项目的内容进行比较。
上面的每个指令都有字节,字和双字版本,并且可以通过使用重复前缀来重复字符串指令。这些指令使用ES:DI和DS:SI对寄存器,其中DI和SI寄存器包含有效的偏移地址,这些地址指向存储在存储器中的字节。SI通常与DS(数据段)相关联,DI通常与ES(额外段)相关联。DS:SI(或ESI)和ES:DI(或EDI)寄存器分别指向源和目标操作数。假定源操作数位于内存中的DS:SI(或ESI),目标操作数位于ES:DI(或EDI)。
对于16位地址,使用SI和DI寄存器,对于32位地址,使用ESI和EDI寄存器。
下表提供了各种版本的字符串指令和假定的操作数空间。
基本指令
操作的寄存器
字节运算
字运算
双字运算
MOVS
ES:DI,DS:SI
MOVSB
MOVSW
MOVSD
LODS
DS:SI
LODSB
LODSW
LODSD
STOS
ES:DI,AX
STOSB
STOS
STOSD
CMPS
DS:SI,ES:DI
CMPSB
CMPSW
CMPSD
SCAS
ES:DI,AX
SCASB
SCASW
SCASD
MOVS
MOVS指令用于将数据项(字节,字或双字)从源字符串复制到目标字符串。源字符串由DS:SI指向,目标字符串由ES:DI指向。
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ecx, len
mov esi, s1
mov edi, s2
cld
rep movsb
mov edx,20 ;message length
mov ecx,s2 ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
s1 db 'Hello, world!',0 ;string 1
len equ $-s1
section .bss
s2 resb 20 ;destination
尝试一下
编译并执行上述代码后,将产生以下结果-
Hello, world!
LODS
在密码术中,凯撒密码是最简单的已知加密技术之一。在这种方法中,要加密的数据中的每个字母都被替换为字母下方固定数量位置的字母。在此示例中,让我们通过简单地将其中的每个字母替换为两个字母来加密数据,因此a将被c,b替换为d等。我们使用LODS将原始字符串'password'加载到内存中。
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ecx, len
mov esi, s1
mov edi, s2
loop_here:
lodsb
add al, 02
stosb
loop loop_here
cld
rep movsb
mov edx,20 ;message length
mov ecx,s2 ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
s1 db 'password', 0 ;source
len equ $-s1
section .bss
s2 resb 10 ;destination
尝试一下
编译并执行上述代码后,将产生以下结果-
rcuuyqtf
STOS
STOS指令将数据项从AL(对于字节-STOSB),AX(对于字-STOSW)或EAX(对于双字-STOSD)复制到目标字符串,该目标字符串由内存中的ES:DI指向。以下示例演示了如何使用LODS和STOS指令将大写字符串转换为其小写值-
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ecx, len
mov esi, s1
mov edi, s2
loop_here:
lodsb
or al, 20h
stosb
loop loop_here
cld
rep movsb
mov edx,20 ;message length
mov ecx,s2 ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
s1 db 'HELLO, WORLD', 0 ;source
len equ $-s1
section .bss
s2 resb 20 ;destination
尝试一下
编译并执行上述代码后,将产生以下结果-
hello, world
CMPS
CMPS指令比较两个字符串。该指令比较DS:SI和ES:DI寄存器所指向的两个数据项,即一个字节,一个字或一个双字,并相应地设置标志。您还可以将条件跳转指令与此指令一起使用。以下示例演示了使用CMPS指令比较两个字符串-
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov esi, s1
mov edi, s2
mov ecx, lens2
cld
repe cmpsb
jecxz equal ;jump when ecx is zero
;If not equal then the following code
mov eax, 4
mov ebx, 1
mov ecx, msg_neq
mov edx, len_neq
int 80h
jmp exit
equal:
mov eax, 4
mov ebx, 1
mov ecx, msg_eq
mov edx, len_eq
int 80h
exit:
mov eax, 1
mov ebx, 0
int 80h
section .data
s1 db 'Hello, world!',0 ;our first string
lens1 equ $-s1
s2 db 'Hello, there!', 0 ;our second string
lens2 equ $-s2
msg_eq db 'Strings are equal!', 0xa
len_eq equ $-msg_eq
msg_neq db 'Strings are not equal!'
len_neq equ $-msg_neq
尝试一下
编译并执行上述代码后,将产生以下结果-
Strings are not equal!
SCAS
SCAS指令用于搜索字符串中的特定字符或一组字符。要搜索的数据项应该在AL(对于SCASB),AX(对于SCASW)或EAX(对于SCASD)寄存器中。要搜索的字符串应在内存中,并由ES:DI(或EDI)寄存器指向。查看以下程序以了解概念-
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ecx,len
mov edi,my_string
mov al , 'e'
cld
repne scasb
je found ; when found
; If not not then the following code
mov eax,4
mov ebx,1
mov ecx,msg_notfound
mov edx,len_notfound
int 80h
jmp exit
found:
mov eax,4
mov ebx,1
mov ecx,msg_found
mov edx,len_found
int 80h
exit:
mov eax,1
mov ebx,0
int 80h
section .data
my_string db 'hello world', 0
len equ $-my_string
msg_found db 'found!', 0xa
len_found equ $-msg_found
msg_notfound db 'not found!'
len_notfound equ $-msg_notfound
尝试一下
编译并执行上述代码后,将产生以下结果-
found!
重复前缀
REP前缀在字符串指令(例如-REP MOVSB)之前设置时,会根据放置在CX寄存器中的计数器使该指令重复。REP执行该指令,将CX减1,然后检查CX是否为零。重复指令处理,直到CX为零为止。
方向标志(DF)确定操作的方向。
使用CLD(清除方向标志,DF = 0)使操作从左到右。
使用STD(设置方向标志,DF = 1)使操作从右到左。
REP前缀也有以下变化:
REP:这是无条件的重复。重复该操作,直到CX为零为止。
REPE或REPZ:这是有条件的重复。当零标志指示等于/零时,它将重复操作。当ZF表示不等于零或CX为零时,它将停止。
REPNE或REPNZ:这也是有条件的重复。当零标志指示不等于/零时,它将重复操作。当ZF指示等于/零或CX减为零时,它将停止。
上一节: 汇编语言 数字
上一节
下一节: 汇编语言 数组
下一节
查看笔记 分享笔记
笔记内容:
称呼:
Email:
站点:
分享笔记 重置
分类导航
前端
Ajax 教程
Angular 教程
Aurelia 教程
Bootstrap 教程
ChartJS 教程
CSS 教程
ES6 教程
FontAwesome 教程
HTML 教程
HTML 字符集 教程
HTML 游戏 教程
JavaScript 教程
jQuery 教程
Less 教程
React 教程
Sass 教程
Stylus 教程
TypeScript 教程
Unity 教程
Vue.js 教程
WebAssembly 教程
XAML 教程
颜色 教程
服务端
C# 教程
C++ 教程
COBOL 教程
C语言 教程
Fortran 教程
Go 教程
Groovy 教程
Java 教程
JSP 教程
JVM 教程
Kotlin 教程
Lisp 教程
Lua 教程
Node.js 教程
Pascal 教程
Perl 教程
PHP 教程
Python 教程
Python 3 教程
Ruby 教程
Rust 教程
Scala 教程
Spring 教程
Spring Boot 教程
Spring Cloud 教程
VB.Net 教程
移动端
Android 教程
IOS 教程
Objective-C 教程
React Native 教程
Swift 教程
小程序 教程
数据库
Access 教程
DB2 教程
Mariadb 教程
Memcached 教程
MongoDB 教程
MySQL 教程
Neo4j 教程
PL/SQL 教程
PostgreSQL 教程
Redis 教程
SQL 教程
SQL Server 教程
SQLite 教程
T-SQL 教程
数据格式
Jackson 教程
JSON 教程
SVG 教程
XML 教程
开发工具
ActiveMQ 教程
Ant 教程
Apache HttpClient 教程
Apache POI PPT 教程
AWS 教程
Docker 教程
ElasticSearch 教程
ExpressJS 教程
GIT 教程
GitLab 教程
Google Maps 教程
Gradle 教程
Java NIO 教程
JavaFX 教程
JavaMail 教程
JDBC 教程
jMeter 教程
JPA 教程
jsoup 教程
Junit 教程
KoaJS 教程
Kubernetes 教程
Log4j 教程
Logstash 教程
Lucene 教程
Makefile 教程
Maven 教程
RESTful 教程
Sed 教程
SEO 教程
Servlet 教程
SLF4J 教程
Socket.IO 教程
Struts 教程
SVN 教程
TestNG 教程
UML 教程
UNIX / LINUX 教程
WebSocket 教程
WPF 教程
xStream 教程
区块链 教程
数据处理
Flink 教程
Flume 教程
Hadoop 教程
Hbase 教程
Hive 教程
Kafka 教程
Kibana 教程
MapReduce 教程
MATLAB 教程
MyBatis 教程
Pig 教程
R语言 教程
Solr 教程
Spark 教程
Storm 教程
Zookeeper 教程
大数据分析 教程
数据仓库 教程
数据挖掘 教程
计算机基础
HTTP 教程
IPv4 教程
IPv6 教程
Ubantu 教程
WebServices 教程
嵌入式系统 教程
操作系统 教程
数据结构和算法 教程
汇编语言 教程
物联网 教程
电子电路基础 教程
编译器设计 教程
网站开发 教程
计算机 教程
计算机基础 教程
计算机网络 教程
设计模式 教程
AI
CNTK 教程
Keras 教程
PyTorch 教程
TensorFlow 教程
人工智能 教程
机器学习 教程
Python 技术
Django 教程
Flask 教程
NumPy 教程
Pandas 教程
Pillow 教程
PyGTK 教程
PyQt5 教程
PySpark 教程
pytest 教程
Python -数据科学 教程
Python MySQL 教程
Python 取证 教程
Python 数据结构 教程
Python 文本处理 教程
Python 网络编程 教程
Python 网页抓取 教程
Python 设计模式 教程
RxPY 教程
SciPy 教程
Seaborn 教程
SymPy 教程
wxPython 教程
框架
Laravel 教程
Web 图标Icon 教程
Web2py 教程
WebGL 教程
WebRTC 教程
WordPress 教程
Yii 教程
Zend Framework 教程
SAP
Crystal Reports 教程