汇编字符串操作指令【微软CL vs. GCC】

这篇具有很好参考价值的文章主要介绍了汇编字符串操作指令【微软CL vs. GCC】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        最近在研究汇编的一些基本指令,在研究过程中通过二进制的反编译学习到了不少汇编的函数、堆栈和一些可以提高代码运行速度的机器指令等汇编语言语法。如字符串的复制可以使用MOV指令逐个字符赋值,也可以使用字符串操作指令减少指令数,提高运行速度。

1. 字符串操作指令 

1.1 字符串装载LODS

        转载指令用于将ESI寄存器所指向的字符串的字符装入到累加寄存器,同时调整ESI的值(加或者减所操作的字节数)。包括LODSB、LODSW、LODSD、LODSQ。

Opcode Instruction Op/
En
64-Bit
Mode
Compat/
Leg Mode
Description
AC LODS m8 ZO Valid Valid For legacy mode, Load byte at address DS:(E)S
into AL. For 64-bit mode load byte at address
(R)SI into AL.
AD LODS m16 ZO Valid Valid For legacy mode, Load word at address
DS:(E)SI into AX. For 64-bit mode load word at
address (R)SI into AX.
AD LODS m32 ZO Valid Valid For legacy mode, Load dword at address
DS:(E)SI into EAX. For 64-bit mode load dword
at address (R)SI into EAX.
REX.W + AD LODS m64 ZO Valid N.E. Load qword at address (R)SI into RAX.
AC LODSB ZO Valid Valid For legacy mode, Load byte at address DS:(E)S
into AL. For 64-bit mode load byte at address
(R)SI into AL.
AD LODSW ZO Valid Valid For legacy mode, Load word at address
DS:(E)SI into AX. For 64-bit mode load word at
address (R)SI into AX.
AD LODSD ZO Valid Valid For legacy mode, Load dword at address
DS:(E)SI into EAX. For 64-bit mode load dword
at address (R)SI into EAX.
REX.W + AD LODSQ ZO Valid N.E. Load qword at address (R)SI into RAX.

1.2 字符串存储STOS

        字符串存储指令用于将累加寄存器值存储到EDI所指向的地址,也就是替换字符,同时调整EDI的值(加或者减所操作的字节数)。包括STOSB、STOSW、STOSD、STOSQ。

Opcode Instruction Op/
En
64-Bit
Mode
Compat/
Leg Mode
Description
AA STOS m8 NA Valid Valid For legacy mode, store AL at address ES:(E)DI;
For 64-bit mode store AL at address RDI or
EDI.
AB STOS m16 NA Valid Valid For legacy mode, store AX at address ES:(E)DI;
For 64-bit mode store AX at address RDI or
EDI.
AB STOS m32 NA Valid Valid For legacy mode, store EAX at address
ES:(E)DI; For 64-bit mode store EAX at address
RDI or EDI.
REX.W + AB STOS m64 NA Valid N.E. Store RAX at address RDI or EDI.
AA STOSB NA Valid Valid For legacy mode, store AL at address ES:(E)DI;
For 64-bit mode store AL at address RDI or
EDI.
AB STOSW NA Valid Valid For legacy mode, store AX at address ES:(E)DI;
For 64-bit mode store AX at address RDI or
EDI.
AB STOSD NA Valid Valid For legacy mode, store EAX at address
ES:(E)DI; For 64-bit mode store EAX at address
RDI or EDI.
REX.W + AB STOSQ NA Valid N.E. Store RAX at address RDI or EDI.

1.3 字符串传送MOVS

        字符串传送指令用于将ESI所指向的字符串传送到EDI所指向的地址,同时调整ESI和EDI的值(加或者减所操作的字节数)。包括MOVSB、MOVSW、MOVSD、MOVSQ。

Opcode Instruction Op/
En
64-Bit
Mode
Compat/
Leg Mode
Description
A4 MOVS m8, m8 ZO Valid Valid For legacy mode, Move byte from address
DS:(E)SI to ES:(E)DI. For 64-bit mode move
byte from address (R|E)SI to (R|E)DI.
A5 MOVS m16, m16 ZO Valid Valid For legacy mode, move word from address
DS:(E)SI to ES:(E)DI. For 64-bit mode move
word at address (R|E)SI to (R|E)DI.
A5 MOVS m32, m32 ZO Valid Valid For legacy mode, move dword from address
DS:(E)SI to ES:(E)DI. For 64-bit mode move
dword from address (R|E)SI to (R|E)DI.
REX.W + A5 MOVS m64, m64 ZO Valid N.E. Move qword from address (R|E)SI to (R|E)DI.
A4 MOVSB ZO Valid Valid For legacy mode, Move byte from address
DS:(E)SI to ES:(E)DI. For 64-bit mode move
byte from address (R|E)SI to (R|E)DI.
A5 MOVSW ZO Valid Valid For legacy mode, move word from address
DS:(E)SI to ES:(E)DI. For 64-bit mode move
word at address (R|E)SI to (R|E)DI.
A5 MOVSD ZO Valid Valid For legacy mode, move dword from address
DS:(E)SI to ES:(E)DI. For 64-bit mode move
dword from address (R|E)SI to (R|E)DI.
REX.W + A5 MOVSQ ZO Valid N.E. Move qword from address (R|E)SI to (R|E)DI.

 1.4 字符串扫描SCAS

        字符串扫描指令用于将累加寄存器的内容与EDI所指向的字节、双字或四字进行比较,并调整EDI的值(加或者减所操作的字节数)。包括SCASB、SCASW、SCASD、SCASQ。

Opcode Instruction Op/
En
64-Bit
Mode
Compat/
Leg Mode
Description
AE SCAS m8 ZO Valid Valid Compare AL with byte at ES:(E)DI or RDI, then
set status flags.*
AF SCAS m16 ZO Valid Valid Compare AX with word at ES:(E)DI or RDI, then
set status flags.*
AF SCAS m32 ZO Valid Valid Compare EAX with doubleword at ES(E)DI or
RDI then set status flags.*
REX.W + AF SCAS m64 ZO Valid N.E. Compare RAX with quadword at RDI or EDI
then set status flags.
AE SCASB ZO Valid Valid Compare AL with byte at ES:(E)DI or RDI then
set status flags.*
AF SCASW ZO Valid Valid Compare AX with word at ES:(E)DI or RDI then
set status flags.*
AF SCASD ZO Valid Valid Compare EAX with doubleword at ES:(E)DI or
RDI then set status flags.*
REX.W + AF SCASQ ZO Valid N.E. Compare RAX with quadword at RDI or EDI
then set status flags.

 1.5 字符串比较CMPS

        字符串比较指令用于将ESI所指向的数据与EDI所指向的数据进行比较,同时调整ESI和EDI的值(加或者减所操作的字节数)。包括CMPSB、CMPSW、CMPSD、CMPSQ。

Opcode Instruction Op/
En
64-Bit
Mode
Compat/
Leg Mode
Description
A6 CMPS m8, m8 ZO Valid Valid For legacy mode, compare byte at address DS:(E)SI with
byte at address ES:(E)DI; For 64-bit mode compare byte
at address (R|E)SI to byte at address (R|E)DI. The status
flags are set accordingly.
A7 CMPS m16, m16 ZO Valid Valid For legacy mode, compare word at address DS:(E)SI
with word at address ES:(E)DI; For 64-bit mode
compare word at address (R|E)SI with word at address
(R|E)DI. The status flags are set accordingly.
A7 CMPS m32, m32 ZO Valid Valid For legacy mode, compare dword at address DS:(E)SI at
dword at address ES:(E)DI; For 64-bit mode compare
dword at address (R|E)SI at dword at address (R|E)DI.
The status flags are set accordingly.
REX.W + A7 CMPS m64, m64 ZO Valid N.E. Compares quadword at address (R|E)SI with quadword
at address (R|E)DI and sets the status flags accordingly.
A6 CMPSB ZO Valid Valid For legacy mode, compare byte at address DS:(E)SI with
byte at address ES:(E)DI; For 64-bit mode compare byte
at address (R|E)SI with byte at address (R|E)DI. The
status flags are set accordingly.
A7 CMPSW ZO Valid Valid For legacy mode, compare word at address DS:(E)SI
with word at address ES:(E)DI; For 64-bit mode
compare word at address (R|E)SI with word at address
(R|E)DI. The status flags are set accordingly.
A7 CMPSD ZO Valid Valid For legacy mode, compare dword at address DS:(E)SI
with dword at address ES:(E)DI; For 64-bit mode
compare dword at address (R|E)SI with dword at
address (R|E)DI. The status flags are set accordingly.
REX.W + A7 CMPSQ ZO Valid N.E. Compares quadword at address (R|E)SI with quadword
at address (R|E)DI and sets the status flags accordingly.

2. 示例

        如下的字符串复制函数C代码在经过编译器编译后,不同的编译器编译参数将产生不同的机器码,代码中的dst[n] = src[n]语句经过编译后可能会使用到字符串操作指令。以下是casm.c源文件中的copy_str函数:

void copy_str(void)
{
	char src[32] = "this is a string";
	char dst[32] = "";
	
	for(int n = 0; n < 32; n++)
	{
		dst[n] = src[n];
	}
	
	printf("copy_str called: %s\n", dst);
}

        本文编译示例代码使用的CL编译器的版本是用于 x86 的 Microsoft (R) C/C++ 优化编译器 19.29.30133 版,GCC版本是4.7.2。 

2.1 微软CL编译

2.1.1 不使用优化

        在命令行运行如下命令编译并链接生成可执行程序:

CL /c casm.c
LINK /SUBSYSTEM:CONSOLE /RELEASE casm.obj

         不使用优化生成的机器码如下图所示,CL编译器使用多条MOV指令来复制字符串:

汇编字符串操作指令【微软CL vs. GCC】

2.1.2 使用O1优化(优选空间)

        在命令行运行如下命令编译并链接生成可执行程序:

CL /c /O1 /GA /w /TC /nologo /Fo casm.c
LINK /SUBSYSTEM:CONSOLE /RELEASE casm.obj

        示例copy_str函数编译后对应的机器码如下图所示,可以看到地址为0x00AC1048等地址使用5次MOVS指令复制了17字符“this is a string",0x00AC1050、0x00AC1054等地址使用了5次STOS指令来将后面的15个字节置为0。如下图所示:

汇编字符串操作指令【微软CL vs. GCC】

2.1.3 使用O2优化(优选速度)

        在命令行运行如下命令编译并链接生成可执行程序:

CL /c /O2 /GA /w /TC /nologo /Fo casm.c
LINK /SUBSYSTEM:CONSOLE /RELEASE casm.obj

         CL编译器采用O2选项编译后的机器码如下图所示,代码非常精简,使用MOVAPS(Move Aligned Packed Single-Precision Floating-Point Values)指令复制字符串,如下图所示:

汇编字符串操作指令【微软CL vs. GCC】

2.2 GCC编译

2.2.1 不使用优化

        在命令行运行如下命令编译并链接生成可执行程序:

gcc -std=c99 .\casm.c -o .\casmgcc.exe

         使用gcc编译后的机器码如下图所示,使用了REP指令和MOVS指令逐个复制字符串,MOVS共计执行17次,如下图所示:

汇编字符串操作指令【微软CL vs. GCC】

2.2.2 使用O1优化

        在命令行运行如下命令编译并链接生成可执行程序:

gcc -std=c99 -O1 .\casm.c -o .\casmgcc.exe

         使用gcc编译后的机器码如下图所示,使用了REP指令和MOVS指令逐个复制字符串,MOVS共计执行17次,为了调用printf函数,gcc还重新分配了stack空间并调用了43次STOS指令,如下图所示:

汇编字符串操作指令【微软CL vs. GCC】

2.2.3 使用O2优化

         在命令行运行如下命令编译并链接生成可执行程序:

gcc -std=c99 -O2 .\casm.c -o .\casmgcc.exe

         生成的机器码如下图所示,可以看到和使用O1优化所生成的机器码基本一样,也是使用了17次MOVS指令复制字符串,如下图所示:

汇编字符串操作指令【微软CL vs. GCC】

3. 总结 

        字符串操作指令可以简化字符串的拷贝等操作,CL和GCC编译器各具特色,CL编译器的O2优化可以生成非常精简的机器码。另外,GCC编译器在处理字符串复制操作时,其使用的指令数多于CL编译器。文章来源地址https://www.toymoban.com/news/detail-462350.html

到了这里,关于汇编字符串操作指令【微软CL vs. GCC】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ARM汇编】字符串大小写转换

    CSDN话题挑战赛第1期 活动详情地址 :话题PK赛 参赛话题 :汇编知识分享 话题描述 :我们的计算机知识就像一座金字塔,底层是数学,上面是数字电路,然后是汇编,再往上是操作系统、网络、数据库、高级编程语言、框架等等…我们不可能精通这个金子塔的每一层, 但是

    2024年01月16日
    浏览(44)
  • 汇编语言(Assembly Language)习题:键盘输入一个字符串,试将其中的小写字母转换为大写字母,其它字符保持不变。

    前置知识:汇编语言常用系统功能调用(如果懂直接跳过看题目详解) 格式: 功能:从键盘输入字符的ASCII码送入寄存器AL中,并送显示器显示。 格式: 功能:将DL寄存器中的字符送显示器显示,如果DL中为〈CTRL〉+〈BREAK〉的ASCII码,则退出。 格式: 功能:将DL寄存器中的字

    2024年02月03日
    浏览(33)
  • 正则表达式 vs. 字符串处理:解析优势与劣势

    1. 正则表达式起源与演变 正则表达式(Regular Expression)最早由美国数学家斯蒂芬·科尔内基(Stephen Kleene)于1956年提出,用于描述字符串的模式匹配规则。随后在计算机领域得到广泛应用,成为文本处理和匹配的重要工具。 正则可视化 | 一个覆盖广泛主题工具的高效在线平台

    2024年03月27日
    浏览(38)
  • SQL Server 查找字符串LIKE vs SUBSTRING vs LEFT/RIGHT vs CHARINDEX

    开发人员经常需要在数据库表中查询以某种文本模式开始和/或结束的记录。例如,查找名字以“DAV”开头的所有员工。 根据我的经验,SQL 开发人员通常依赖 4 个常用函数来实现这一点。 就在那时,这位好奇的顾问决定将它们正面交锋:LIKE vs SUBSTRING vs LEFT / RIGHT vs CH

    2024年02月05日
    浏览(32)
  • Python 字符串操作之字符串的截取

    字符串的截取是实际应用中经常使用的技术,被截取的部分称为“子串”。Java中使用函数substr()获取子串,C#使用函数substring()获取子串。而Python由于内置了序列,可以通过前面介绍的索引、切片获取子串,也可以使用函数split()来获取。字符串也属于序列。 下面这段代码使用

    2024年02月06日
    浏览(67)
  • Python字符串操作之如何提取子字符串

    在 Python 中,字符串是一种非常常见的数据类型,经常需要对字符串进行各种操作,其中提取子字符串是一个非常常见的需求。本文将介绍几种在 Python 中提取子字符串的方法。 方法一:使用字符串切片 在 Python 中,可以使用字符串切片的方式来提取子字符串。字符串切片通

    2024年02月09日
    浏览(36)
  • 【Lua语法】字符串操作、字符串中的方法

    注意:这些方法不会改变原字符串,只会返回一个新字符串

    2024年02月15日
    浏览(45)
  • 【Kotlin】字符串操作 ① ( 截取字符串函数 substring | 拆分字符串函数 split | 解构语法特性 )

    Kotlin 中提供了 截取字符串函数 substring , 可接收 IntRange 类型的参数 , 这是 整数范围 类型 ; 截取字符串函数 substring 函数原型为 : 整数范围类型 : 其整数范围是 {0 , 1 , 2 , 3} ; 其整数范围是 {0 , 1 , 2} ; 代码示例 : 执行结果 : 拆分字符串函数 split 返回的是 List 集合 ; 拆分字符串函

    2023年04月08日
    浏览(43)
  • python 字符串操作

    截取字符串中数字,并转化为数字 str1 = str[4:] #得到字符串 \\\'1800\\\',   num = eval(str1) #将字符串转换为数字,eval 用于比较复杂的情况,也可以直接用int(str1) #eval用于更复杂的情况,比如  str_num = \\\"(2+3)*5\\\" num = eval(str_num) 对于单个分隔符时 可以用 temp = str.split(\\\',\\\') 多个分隔符 str

    2024年02月15日
    浏览(32)
  • [字符串操作] 单词替换

    题目描述 输入一个字符串,以回车结束(字符串长度=100)。该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写。现需要将其中的某个单词替换成另一个单词,并输出替换之后的字符串。 关于输入 输入包括3行:   第1行是包含多个单词的字符串

    2024年02月04日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包