|
除了把字符串从一个内存位置传送到另一个内存位置外(MOVS 指令),还有用于把内存中的字符串值加载到寄存器中以及传回内存位置中的指令。
LODS 指令用于把内存中的字符串值传送到 EAX 中,其格式为:
LODSL: 把一个双字 (4字节) 加载到 EAX 中 Intel 文档使用 LODSD 加载双字,GNU 汇编器使用 LODSL 。
LODS 指令使用 ESI 作为隐含源操作数,ESI 中必须包含要加载的字符串所在的内存地址。数据传送完后,LODS 按照加载的数据数量递增或递减(取决于 DF 标志) ESI 寄存器。
STOS 指令把字符串值存放到 EAX 之后,可以使用 STOS 将它放到另一个内存位置中。STOS 也有 3 种格式:
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! |
|