zoukankan      html  css  js  c++  java
  • 16位汇编第八讲指令第四讲

            16位汇编第八讲指令第四讲

    一丶串操作类指令

    1.什么是串操作?

      1.串操作指令是8086指令系统中比较独特的一类指令,采用比较特殊的数据串寻址方式,在操作主存连续区域

    的数据是,特别好用.因而比较常用

    简而言之,就是内存中的一段数据,拷贝/读取/修改... 到另一块另内存

    重点掌握  MOVS  STOS  LODS CMPS SCAS REP

    2.串操作的简介

      1.串操作指令的操作数,是驻村中连续存放的数据串(String 注意string表示串的意思)--也就是一段数据在内存中

    是连续的,以字或者字节排列

      2.串操作指令的操作对象是以字(Word)为单位的字串,或者字节(Byte)为单位的字节串--简单理解就是我要操作

    1个字节大小,还是两个字节大小

    3.串的操作

      串的操作一般使用 SI(源寄存器)和 DI(目的寄存器),可以使用端超越DS:[SI]

      或者目的寄存器 DI  ES:[DI]

    每次执行一次串操作,那么SI和DI则会自动修改,地址自增

    当然地址自增是看方向标志的  DF  我们要想复制的时候,让其内存自增复制,那么就用CLD让方向初始为自增

    否则 反向复制的话就用STD指令让地址自减

    4.串操作指令中的串传送指令(MOVS)

    作用:

      把字节或者字操作数从内存的源地址,传送到目的地址

    分别有两个指令,一个是字节串传送,一个是字传送

    MOVSB (后缀b代表byte的意思)  MOVSW(后缀w代表字的意思)

    指令:

      MOVSB    ES:[DI] <- DS:[SI]  从si内存中取出一个字节的数据,复制到DI中

        SI<-SI±1,DI<-DI±1  地址随着方向标志自增1或者自减1

      MOVSW    ES:[DI] <- DS:[SI]  从si内存中取出一个字的数据,复制到DI中

        SI<-SI±2,DI<-DI±2  地址随着方向标志自增2或者自减2

     使用例子:

      

    主要是两个花红框的地方,意思是什么,第一个画红框的内容

    1.定义一个源地址,里面的内容是HELLO  也就是内存的内容是Hello

    2.定义一个目标地址,里面的内容是申请了100个字节,然后初始化为零

    第二个画红框的内容

    1.首先给si设置偏移这里使用lea设置的, 我们也可以写成   mov si,offset g_szSrc,下面的目的也是一样

    2.给目的设置偏移

    3.使用movsb,从si内从中取出一个字节,设置到目的内存中

    可以看出,方向标志位默认是往下自增的,我并没有使用CLD设置,所以SI 和DI复制完成后,内存就会自增

     会C语言的请看这条注释 : 在C语言中,这个命令就相当于 memcpy(内存拷贝)每次拷贝几个字节,不懂汇编的滤过

    当然我们可以使用 MOVSW 只不过一次拷贝两个字节了.具体的自己手工尝试.

     5.串操作指令中的串存储指令STOS(store string)

    作用: 把AL或者AX数据传送到目的地址

    C语言的请看: 在C语言中,这条命令相当于 memset,清空的作用

    这个就简单了,把寄存器的数据,传送到目的寄存器中,也就是 ES:[DI]中

    ES:[DI]<-AL/AX

    对于这里我说一下ES 和DS 上面我们使用的时候,并没有使用段超越指令,为什么,因为我们的DI 和SI都是数据区了,

    也就是说不用使用段超越了,否则你需要自己加,一般来说,ES和DS两个段都是合并到一起的

    STOSB,STOSW

    分别对应两条指令

        STOSB 字节串存储  ES[DI]<-AL,把AL的数据,放到DI中  

          按照方向标志,DI<-DI±1  自增或者自减1

        STOSW 字串存储: ES:[DI]<-Ax ,把AX中的数据,放到DI中

          按照方向标志,DI<-DI±2  自增或者自减2

    使用例子,字节串存储

      

    第一框,代码是给al一个3,然后通过段存储的命令,把3给DI存储

    反汇编单步调试,已经完成一个字节保存了,现在看下DI 06的偏移处是不是3

    是3,完成了操作

    STOSW 则是把AX中的数据,放到DI中,放两个字节,也就是一个字,因为AX是16位寄存器.

    具体自己测试即可.

    6.串操作指令,串读取LODS(load string)

    作用:

       把指定的主存单元的数据传送给AL,或者AX

    看到这里已经明白了吧,上面的是吧AL,或者AX中的内容存储到DI中,这个则是读取到DI中,唯一不同的则是从源寄存器中读取(也就是SI)

    LODSB  字节串读取  AL<-DS:[SI]  按照方向标志,自增或者自减1  SI<-SI±1

    LODSW 字读取         AX<-DS:[SI]  按照方向标志,自增或者自减2  SI<-SI±2

    使用例子:

      

    现在可以看到AX中的值是0b46,而SI中的偏移加上段地址所在的物理地址是hello

    我们使用了 字读取,也就是读取两个字节,也就是说AX中的值会变为  he 这两个字符的ASCII码

    具体的字节读取,自己测试便知道了

     7.串操作命令,串比较CMPS(compare string)

    作用:

      讲主存中的源操作数减去目的操作数,然后设置标志位,进位比较两个操作数之间的关系

    简而言之:

      意思就是  源内存中的数(可以理解为数,也可能是字符串的ASCII码) 减去 目的内存中的数,根据结果设置标志位

    比如  源内存 的数字是  1  目的内存中  也是1  那么 1 -1 就为0,0是结果,根据结果设置一下标志位  则ZF = 1,也就是源和目的相等

    C语言的请看:  相当于memcmp(内存比较) 不懂C语言的滤过

    也有两个比较,分别是字比较,还有字节比较

    字节比较:  CMPSB  DS:[SI]-ES:[DI]     根据方向的标志自增或者自减1  SI<-SI±1,DI<-DI±1

    字比较:      CMPSB  DS:[SI]-ES:[DI]     根据方向的标志自增或者自减2 SI<-SI±2,DI<-DI±2

    使用例子,字节比较

      

    看下反汇编代码,然后看下标志位

    结果相当,则ZF位为1,如果hello 五个字节都要比较,则来五次即可. (下面还有重复前缀指令,暂时是来五次)

    具体的字比较,自己测试便知道

    8.串操作指令,串扫描SCAS(Scan String)

    作用:

      将AL/AX减去目的操作数,以便设置标志,进位比较AL/AX与操作数的关系

    简而言之:

      就是你要搜索的字节,放到AL,或者AX中,然后会和DI去比较,然后根据结果设置标志

    C语言的请看: 在C语言中,这个相当于 memchr命令

    SCASB       AL-ES:[DI]  根据方向标志自增或者自减1  DI<-±1

    SCASW      AX-ES:[DI]  根据方向标志自增或者自减2  DI<-±2

    使用例子:

    现在是68 - 去内存中DI中的值,也是68

    设置标志位,AL中寄存器的值减去DI中的值,根据结果设置标志位,因为68-68结果就是0,所以对应的零标志位置位了

    有可能68-69,就是负数了,所以CF位会置位

     二丶重复前缀指令(repeat)

    1.什么是重复前缀指令?

      简单理解为就是为串操作单独提供的循环指令,比如我们上面要用MOVS串操作指令的时候,把源寄存器中的值,拷贝到目的寄存器中,假设我们有个HELLO 我们要使用五次 MOVSB命令才能拷贝过去

    现在提供了一个为串操作的循环

    重复前缀分为两类,3条指令

    1.配合使用,MOVS,STOS,LODS的时候,使用指令REP前缀,不影响标志

    2.配合使用 CMPS,SCAS,指令,使用REPZ和REPNZ前缀

    然后重复次数放到cx寄存器中

    例如

      

    mov cx,3
    rep movsb 

    代表我要重复三次,movsb的指令,注意,根据方向标志,每次自增或者自减1,因为你使用的movsb

    REP指令的作用就是 当CX ≠ 0的时候,继续传送

    REPZ,和REPNZ解析

    REPZ:

      1.每次执行串指令,则CX-1

      2.判断零标志位(ZF)是否为零 (也就是不想等)

      3.如果CX == 0,或者 ZF == 0 (不想等)则重复执行结束

    注意可以简单理解为,    cx !=0 并且  zf == 1 的时候继续循环

    REPNZ:

           1.每次执行串指令,则CX-1

      2.判断零标志位(ZF)是否为1 (也就是想等)

      3.如果CX == 0,或者 ZF ==1 (想等)则重复执行结束

     REPNZ/REPNE的前缀,可以简单理解为   cx != 0  && zf ==0 的时候继续

    使用就很简单了,上次我们要拷贝的时候必须给五次,这次直接给CX一个值,然后利用前缀指令即可.

     三丶控制转移指令

    控制转移指令,用于实现分支,循环,过程等程序的接口,是仅次于传送指令的常用指令

    一般来说控制转移指令都是修改IP的偏移或者CS段寄存器的值,让代码跳转(坏处: 断CPU的流水线)实现

    程序的执行顺序的改变

    ①丶无条件转移指令

      无条件转移指令,就是说你给一个偏移,可以无条件的跳转到其地放执行

    JMP指令(无条件转移指令)

    JMP指令有2个种类,4个类型

    1.段内转移

    2.段间转移

      段内转移:

        段内转移,就是在一个段中的跳转

    又分为短转移,和近转移

    短转移(short): 短转移就是一次只能跳一个字节的大小,也就是 ±127

    近转移(near): 近转移则是能跳转 -32767 -> 327678大小

    例子:

      

    JMP SHORT 地址/标号

    跳转到地址或者标号的地方

    近转移

    对于近转移来说,机器码是一个字节,E9是操作码,而0100则是偏移,就是说你跳转的偏移的大小是多少

    段间转移

       段间转移,则是去另一个段去跳转

    JMP FAR PTR  地址,标号

    例子:

      

    对于段间转移,则是 段地址:偏移 的形式去转移的,CS的值会修改为段地址,IP会修改为偏移

    注意二进制机器码,也是这样的,这个可以自己修改的,因为让代码JMP到自己的代码,然后在JMP回去,就实现了HOOK指令

    JMP有两种寻址指令

    直接寻址方式

     

    JMP AX

    地址放在寄存器当中

    间接寻址方式

      

    JMP  word ptr [BX]  ;需要指明一下

    总结

    短转移:  使用 short 关键字 例如  jmp short 标号/地址偏移

    近转移: 使用  near ptr  例如 jmp near ptr 标号/地址偏移

    远转移:  使用 far ptr    例如 jmp  far ptr 标号/地址偏移

    然后近转移和短转移,可以直接使用jmp,在编译器中,会自动选择相应的方式去转移

    四丶条件转移

     上面说的都是强制转移,现在我们需要使用条件转移指令,比如根据标志位去转移

    JCC  (JCC是一个比喻,并没有这条命令,可以吧CC看做任何条件)

    JCC  标号

    CC条件成立则跳转到标号,否则程序继续顺序执行下一条指令

    操作数标号,使用短转移,成为相对寻址方式

    其中CC是一张表组成

    看到这张表很难记,有个小窍门

    1.  z  zero(零的意思)/E  (equal)

      如果为z则是位零的意思,为e则是相等的意思

    比如

      jz/je  等于零,或者相等,其中判断的是ZF位

    N表示取反的意思

    比如

      JS  SF = 1 表示符号为负

      JNS 不看也知道SF = 0 符号位正

    其中每个标志位都有一个  判断是否相等或者不想等

    比如 CF位

      jC  那么代表CF =1 jNC 那么表示CF = 0

    对于上面还不够,因为我们还要判断是否 大于,小于 高于,低于 (高于,低于 是用于无符号的判断,大于小于则是用于符号的判断)

    G  有符号的 大于判断

    L   有符号的小于判断

    A  无符号的高于判断

    B 无符号的低于判断

    比如,我要判断CF位小于0   JB

    如果是CF大于零,则  JNB (不低于) JAE (A是高于  高于等于)

     作业以及资料下载链接: 链接:http://pan.baidu.com/s/1boQijU3 密码:nr3a

  • 相关阅读:
    MySQL表的四种分区类型
    微信开发配置(Yii框架下的开发)
    一道编程题—输出字符串内重复的数字
    无序数组内查找指定值(快速查找)
    指针
    chmod
    cookie和session的区别
    使用keytool生成证书
    人大金仓修改最大连接数
    数据库链接地址
  • 原文地址:https://www.cnblogs.com/iBinary/p/7482525.html
Copyright © 2011-2022 走看看