当前位置:软件学习 > 其它软件 >>

AT&T汇编处理字符串

一.传送字符串
把字符串从一个内存位置复制到另一个内存位置。
 
 
1.MOVS
3种格式:
MOVSB:传送单一字节
MOVSW:传送一个字(2字节)
MOVSL:传送一个双字(4字节)
MOVS使用隐含的源(ESI)、目的(EDI)操作数。
两种加载ESI、EDI值的方式:
1)间接寻址:
movl $output,  %edi
2)lea指令加载一个对象的有效地址
leal output,  %esi
 
每次执行MOVS指令时,数据传送后,ESI和EDI寄存器会自动改变,为另一次传送做准备。
ESI、EDI可能递增也可能递减,这取决于EFLAGS中的DF标志。如果DF被清零则递增,DF被设置,则递减。
CLD将DF清零
STD设置DF标志
示例:
[cpp]  
# An example of the MOVS instructions  
.section .data  
str:  
    .ascii  "Hi AT&T.\n"  
  
.section .bss  
    .lcomm  output, 9  
  
.section .text  
.global _start  
  
_start:  
    nop  
  
    leal    str,    %esi  
    leal    output, %edi  
  
    movsb  
    movsw  
    movsl  
  
    movl    $1,     %eax  
    movl    $0,     %ebx  
    int     $0x80  
调试:
liury@liury-laptop:~/program/asm/working_with_string/movs_example$ make
as -gstabs -o movs_example.o movs_example.s
ld -o movs_example movs_example.o
liury@liury-laptop:~/program/asm/working_with_string/movs_example$ ls
makefile  movs_example  movs_example.o  movs_example.s
liury@liury-laptop:~/program/asm/working_with_string/movs_example$ gdb ./movs_example 
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/liury/program/asm/working_with_string/movs_example/movs_example...done.
(gdb) l
1 # An example of the MOVS instructions
2 .section .data
3 str:
4 .ascii  "Hi AT&T.\n"
6 .section .bss
7 .lcomm  output, 9
9 .section .text
10 .global _start
(gdb) b *_start+1
Breakpoint 1 at 0x8048075: file movs_example.s, line 15.
(gdb) r
Starting program: /home/liury/program/asm/working_with_string/movs_example/movs_example 
 
Breakpoint 1, _start () at movs_example.s:15
15 leal  str, %esi
(gdb) n
16 leal  output, %edi
(gdb) print /x $esi
$1 = 0x8049094
(gdb) print /x str
$2 = 0x41206948
(gdb) print /x &str
$3 = 0x8049094
(gdb) n
18 movsb
(gdb) x /9cb &output
0x80490a0 <output>: 0 '\000'0 '\000'
0 '\000'0 '\000'
0 '\000'0 '\000'
0 '\000'0 '\000'
0x80490a8 <output+8>: 0 '\000'
(gdb) x /s &output
0x80490a0 <output>: ""
(gdb) n
19 movsw
(gdb) x /s &output
0x80490a0 <output>: "H"
(gdb) n
20 movsl
(gdb) x /s &output
0x80490a0 <output>: "Hi "
(gdb) n
22 movl  $1, %eax
(gdb) x /s &output
0x80490a0 <output>: "Hi AT&T"
(gdb) c
Continuing.
 
Program exited normally.
(gdb) q
 
对于要传送大型字符串,可用循环:
[cpp] 
    leal    datas,  %esi  
    leal    output, %edi  
    mvol    $100,   %ecx  
    cld  
loop_cp:  
    movsb  
    loop    loop_cp  
 
2.REP
可更简单地传送大型字符串。它自己并不执行什么操作,这条指令用于按照特定次数重复执行字符串指令,由ECX寄存器中的值进行控制。例如
[cpp]  
leal    datas,  %esi  
leal    output, %edi  
mvol    $100,   %ecx  
cld  
rep     movsb  
 
MOVSW,MOVSL传送大型字符串效率更高,但小心不能除尽的情况。
 
有些REP指令除监视ECX外还监视ZF(零标志)的状态。
--------------------------------------------------
指令 描述
-------------------------------------------
REPE 等于时重复
REPNE 不等于时重复
REPNZ 不为0时重复
REPZ 为0时重复
---------------------------------------------------
 
二.存储和加载字符串
 
1.LODS
用于把内存中的字符串传送到EAX。三种形式:
LODSB:把一个字节加载到AL
LODSW:把一个字加载到AX
LODSL:把一个双字加载到EAX
 
LODS指令使用ESI寄存器作为隐含的源操作数。ESI必须包含要加载的字符串所在的内存地址。
同样加载后ESI递增或递减取决于DF标志。
 
2.STOS
把字符串从EAX放到一个内存地址。
STOSB:存储AL中一个字节数据
STOSW:存储AX中一个字数据
STOSL:存储EAX中一个双字数据
 
STOS指令使用EDI作为隐含的目标操作数。可方便地与REP配合:
[cpp]  
leal    space,  %esi  
leal    buffer, %edi  
movl    $256,   %ecx  
cld  
lodsb  
rep     stosb  
 
字符串处理示例,小写变大写:
[cpp]  
# Converting lower to upper case  
  
.section .data  
str1:  
    .asciz  "This is a TEST, of the program, hello AT&R!\n"  
len:  
    .int    . - str1  
  
.section .text  
.global _start  
  
_start:  
    nop  
    leal    str1,   %esi  
    movl    %esi,   %edi  
    movl    len,    %ecx  
    cld  
1:  
    lodsb  
  
&n
补充:软件开发 , 其他 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,