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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM