汇编语言 字符串

汇编语言 字符串

上一节: 汇编语言 数字

上一节

下一节: 汇编语言 数组

下一节

汇编语言 字符串

字符串

在前面的示例中,我们已经使用了可变长度的字符串。可变长度字符串可以根据需要包含任意多个字符。通常,我们通过以下两种方式之一指定字符串的长度:

显式存储字符串长度

使用哨兵字符

我们可以使用表示位置计数器当前值的$位置计数器符号来显式存储字符串长度。在以下示例中-

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 教程

相关推荐

怎样套野鸡(怎样套野鸡绊脚)
约彩365官方网站下载

怎样套野鸡(怎样套野鸡绊脚)

📅 10-17 👁️ 9735
盘点方文山给歌手们写过的十大热门歌曲,最后一首把我感动哭了
懒人版韩式炖牛排骨Beef rib stew-Galbi Jjim
365体育官网平台手机

懒人版韩式炖牛排骨Beef rib stew-Galbi Jjim

📅 07-19 👁️ 595
【心得】海盜船cp值首選~RM650i數位電源開箱 @電腦應用綜合討論 哈啦板
八路军为歼灭冈崎大队发起18次冲锋,最终因缺乏重武器功亏一篑!
市级公安局长相当于部队什么职务?军衔和警衔全对照
搜素“螠臹狋彼桒齅荵堧襕哛囘韟滮猱”的成语
约彩365官方网站下载

搜素“螠臹狋彼桒齅荵堧襕哛囘韟滮猱”的成语

📅 07-26 👁️ 3390
淘宝退款记录怎么删除?淘宝退款记录删除了怎么恢复
4s店装一个抬头显示,要多少钱
365现金卡

4s店装一个抬头显示,要多少钱

📅 01-02 👁️ 2611