Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3178015
  • 博文数量: 797
  • 博客积分: 10134
  • 博客等级: 上将
  • 技术积分: 9335
  • 用 户 组: 普通用户
  • 注册时间: 2006-06-22 22:57
个人简介

1

文章分类

全部博文(797)

文章存档

2022年(1)

2021年(2)

2017年(2)

2016年(1)

2015年(4)

2014年(1)

2013年(6)

2012年(6)

2011年(10)

2010年(26)

2009年(63)

2008年(61)

2007年(51)

2006年(563)

我的朋友

分类: C/C++

2012-07-07 16:16:30

 

这只是一个学习笔记,难免会有些杂乱,记录的都是一些汇编中有关String的要点。

1、在汇编语言看来,只要是在内存中连续的存储单元(byte)中存储的东西都叫做“String”,而不管这些东西是不是人可以识别的字符。

2、汇编语言的String是你通过在R额Register中设定相应的值来指定的。比如在EAX中指定String的首地址,在ECX中指定String的长度。

3、String分为Source String和Destination String。Source String就是你读入的String,Destination String就是你要写入的String。它们的区别仅是寄存器的不同

     · Source String使用ESIExtend Source Index作为地址寄存器,使用ECX表示它的长度。

     · Destination String使用EDIExtend Destination Index指向它的地址,同样使用ECX表示它的长度。

     · Data coming from a source string or going to a destination string must begin the trip from, end the trip at, or pass through register EAX.

 

4、STOSB

     这个指令是STOre String by Byte的助记法。它的功能是把某个byte书写到Destination String中多少次。

     它使用以下几个寄存器:

       · EDI 必须指向Destination String。

       · ECX 中存放需要写入的次数。需要写入的东西在AL中。

       · AL 中存放想要在String中存放的数值。

     这时候,如果执行STOSB指令,将会执行下面的两个操作:

       · AL 中存放的一个byte的值被放到EDI所指向的内存中;

       · EDI 加1,这样它就指向了下一个可以写入的单元(byte)。

     这时的ECX(其中存放着“次数”)不会自动减1,需要你自己来设定(使用DEC和LOOP),或者使用下面的命令:

rep stosb

     REP是一个指令前缀,表明CPU应该以什么样的态度对待它之后那个指令(这里是STOSB)

     在这个指令中,还有一个非常重要的地方,就是DF标记位(Direction Flag)。当DF为1时,对于内存的访问是从大到小的(地址),如果DF为0,那么就从小到大。一般都是从小到大。

     有两个指令可以设定DF的值,一个是CLD,一个是STD。前者把DF设为0,后者把DF设为1。即前者为从小到大查找(STOSB中的EDI每次增加1),后者从大到下查找(STOSB中的EDI每次减1)。POPF也会影响DF的值。

     还有几个与STOS相关的指令:

       · STOSB:STOre String by Byte,存储8-bits的数据(AL),EDI每次移动1个byte(根据DF确定方向)

       · STOSW:STOre String by Word,存储16-bits的数据(AX),EDI每次移动2个byte(根据DF确定方向)

       · STOSD:STOre String by Double,存储32-bits的数据(EAX),EDI每次移动4个byte(根据DF确定方向)

     在它们之前使用 REP,全都是对ECX减1。

 

5、LOOP

     如果仅仅使用STOSB指令,那么仅能进行一次写入操作。需要一个循环,同时减少ECX的值,才能不断写入。这可以用两个指令实现:

DoChar: stosb ; Note that there’s no REP prefix! add al,'1' ; Bump the character value in AL up by 1 aaa ; Adjust AX to make this a BCD addition add al,'0' ; Basically, put binary 3 in AL’s high nybble dec ecx ; Decrement the count by 1.. jnz DoChar ; ..and loop again if ECX > 0

     最后的这两个指令也可以用一个指令代替,即LOOP:它首先把ECX减1,然后检查ZF标记位,看是否跳转。当ECX不为0时,跳转,否则就不跳转

DoChar: stosb ; Note that there’s no REP prefix! add al,'1' ; Bump the character value in AL up by 1 aaa ; Adjust AX to make this a BCD addition add al,'0' ; Make sure we have binary 3 in AL’s high nybble loop DoChar ; Go back & do another char until ECX goes to 0


6、MOVSB

     MOVS也有三种形式,都是把数据从 ESI 所指向的内存拷贝到 EDI 所指向的内存,拷贝的次数为 ECX ,根据 DF(Direction Flas) 来确定方向:

       · MOVSB:MOVe String by Byte,每次操作8-bits(1个byte)的数据,每拷贝1个byte的数据ECX减一

       · MOVSW:MOVe String by Word,每次操作16-bits(2个byte)的数据,每拷贝2个byte的数据ECX减一

       · MOVSD:MOVe String by Double,每次操作32-bits(4个byte)的数据,每拷贝4个byte的数据ECX减一

     在这些指令之前使用 REP ,可以把它们变成全自动机关枪,一直执行到 ECX 变成0。

 

7、SCASB

     这个指令和上面两个指令的用法基本相似。它表示SCAn String by Byte,用来搜索字符串。

     它设定以下几个寄存器:

       · DF 设定为0或1,表明搜索的方向是uphill还是downhill。

       · EDI 中存放需要搜索的字符串的地址。我感觉这里有些诡异,为什么不放在ESI中呢?

       · AL 需要查找的东西放在AL中。

       · ECX 最大查找的次数放在ECX中。

     这里使用 REPNE SCASB 进行自动搜索。在搜索过程中,[EDI] 所指向的byte每次都和 AL 中的值进行比较,如果相等,则停止查找。如果不相等,那么 EDI 加1, ECX 减1,继续尝试下一个[EDI]。当搜索找到所要的值的时候,EDI 指向所要查找的 byte 的下一个 byte。它要停下来有两种情况,一是找到AL中的值,一是ECX为0。

     这里的 REPNE 的意思是:Repeat SCASB as long as [EDI] does not equal AL.

     如果使用 REPE 作为前缀:Repeat SCASB as long as [EDI] equals AL.

     SCASB 会设定ZF的值,如果[EDI] 和 AL中的值相同(为0),那么ZF为1,表明找到AL中的值;如果不同(不为0),那么ZF为0,表明没有找到AL中的值。

      · 这样,当使用REPNE时,ZF为1时停下。当使用REPE时,ZF为0时停下。

      · 判断是否是ECX用完时(即找不到和AL相同的值,或全是和AL相同的值),REPNE 用 JNZ,REPE 用 JZ。

阅读(1138) | 评论(0) | 转发(0) |
0

上一篇:windows路径操作API函数

下一篇:Ping 1.2

给主人留下些什么吧!~~