曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 5031|回复: 0
打印 上一主题 下一主题

存储和加载字符串(LODS和STOS)

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2010-8-17 00:19:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
除了把字符串从一个内存位置传送到另一个内存位置外(MOVS 指令),还有用于把内存中的字符串值加载到寄存器中以及传回内存位置中的指令。

LODS 指令用于把内存中的字符串值传送到 EAX 中,其格式为:
      LODSB: 把一个字节加载到 AL 中
      LODSW: 把一个字(2字节)加载到 AX 中
      LODSL: 把一个双字 (4字节) 加载到 EAX 中
Intel 文档使用 LODSD 加载双字,GNU 汇编器使用 LODSL

LODS 指令使用 ESI 作为隐含源操作数,ESI 中必须包含要加载的字符串所在的内存地址。数据传送完后,LODS 按照加载的数据数量递增或递减(取决于 DF 标志) ESI 寄存器。

STOS 指令把字符串值存放到 EAX 之后,可以使用 STOS 将它放到另一个内存位置中。STOS 也有 3 种格式:
      STOSB: 存储 AL 中一个字节数据
      STOSW: 存储 AX 中一个字(2字节)的数据
      STOSL: 存储 EAX 中一个双字 (4个字节) 的数据
STOS 使用 EDI 作为隐含目标操作数,执行 STOS 时,它按照使用的数据长度递增或递减 EDI 的值。STOS 方便之处是可以和 REP 指令一起使用,多次把一个字符串值复制到大型内存区域 -- 如把空格字符(ASCII 码为 0x20)复制到 256字节的缓冲区区域。下面是示例程序:
.section .data
space:
     .ascii " "

.section .bss
     .lcomm buffer, 256

.section .text
.global _start

_start:
     nop
     leal space, %esi
     leal buffer, %edi
     movl $256, %ecx

     cld
     lodsb
     rep stosb

     movl $1, %eax
     movl $0, %ebx
     int $0x80
上面程序将空格符的 ASCII 码加载到 AL 中,然后把它复制到 buffer 标签指向的内存位置中 256 次。在 GDB 中可以看到:
... ...
(gdb) print/x $eax
$1 = 0x20
... ...
(gdb) x/10b &buffer
0x80490a0 <buffer>:    0x20    0x20    0x20    0x20    0x20    0x20    0x20    0x20
0x80490a8 <buffer+8>:    0x20    0x20

LODS 与 STOS 应用示例
LODS 和 STOS 可以用于各种字符串操作。通过 ESI 和 EDI 寄存器指向相同的字符串,可以对字符串执行简单的操作。可以使用 LODS 遍历字符串,一次把一个字符加载到 AL 中,然后对这个字符执行某些操作,最后使用 STOS 将新的字符加载回字符串中。
下面程序将字符串都转换为大写字母:
.section .data
string1:
     .asciz "This is a TEST, of the conversion program!\n"

length:
     .int 43

.section .text
.global _start

_start:
     nop
     leal string1, %esi
     movl %esi, %edi
     movl length, %ecx
     cld
loop1:                   #如果是小写字母则转换为大写字母,否则忽略
     lodsb
     cmpb $'a', %al
     jl skip
     cmpb $'z', %al
     jg skip
     subb $0x20, %al
skip:
     stosb
     loop loop1
end:
     pushl $string1
     call printf
     addl $4, %esp
     pushl $0
     call exit
编译链接:
$ as -gstabs -o convert.o convert.s
$ ld -dynamic-linker /lib/ld-linux.so.2 -o convert -lc convert.o
运行此程序:
$ ./convert
THIS IS A TEST, OF THE CONVERSION PROGRAM!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-14 21:42 , Processed in 0.081649 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表