日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Intel汇编语言程序设计学习-第六章 条件处理-中

發布時間:2025/6/17 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Intel汇编语言程序设计学习-第六章 条件处理-中 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

6.3 ?條件跳轉

6.3.1 ?條件結構

? ? 在IA-32指令集中沒有高級的邏輯結構,但無論多么復雜的結構,都可以使用比較和跳轉指令組合來實現。執行條件語句包括兩個步驟:首先,使用CMPAND,SUB之類的指令修改CPU標志六七次,使用條件跳轉指令測試并導致向新地址的分支轉移。

? ? 例子1:使用CMP指令比較AL0,如果CPU指令設置了零標志,那么JZ(為0則跳轉)指令就跳轉到標號L1處:

cmp al ,0

jz L1

.

.

L1:

?

6.3.2 ?條件跳轉(Jcond)指令

? ? 條件跳轉指令在標志條件為真時分支跳轉到新的目的標號處,如果條件標志為假,那么執行緊跟在跳轉跳轉指令之后的指令。格式如下:

? ? ? ? jcond 目標地址

? ? 格式中的cond指的是一個標志條件,用來表示一個或多個標志的狀態。例如:

? ? ? jc ???如果進位則跳轉

? ? ? jnc ??如果無進位則跳轉

? ? ? jz ???如果為零則跳轉

? ? ? jnz ??如果不為零則跳轉

? ? 我們已經知道算數指令。比較指令和布爾指令幾乎重視會設置標志位、條件跳轉指令檢查標志位的狀態并且根據標志位的狀態決定是否跳轉。

? ? 限制:MASM在默認情況下要求跳轉的目的地址在當前的過程之內,為了突破這種限制,可以聲明一個全局標號(標號后面跟”::”:

jc MyLabel

.

.

MyLabel::


通常,應盡量避免跳轉到當前的過程之外,否則調試程序時會比較困難。

? ? 在Intel386之前,跳轉的目標地址被限制在跳轉指令后的第一條指令+128~-127個字節范圍之內。IA-32處理器可跳轉到當前段內的任何地址。

? ? 使用CMP指令:假設我們想在AX等于5時跳轉到位置L1處。假設AX等于5CMP指令設置了零標志,由于零標志置位了,執行JE指令就會發生跳轉:

? ? cmp ax,5

? ? je ?L1 ??????;相等則跳轉

? ? 如果AX不等于5CMP就會清楚零標志,執行JE指令就不會發生跳轉,在下面的例子中,由于AX小于6而發生了跳轉:

? ? mov ?ax ,5

? ? cmp ?ax,6

? ? jl ????L1 ???;如果小于則跳轉大于是(jg

6.3.3 ?條件跳轉指令的類型

? ? ?IA-32指令集中跳轉中的數目驚人地多,支持根據有符號、無符號整數的比較以及對CPU狀態標志的檢查進行跳轉的一系列指令,跳轉跳轉指令可分成下面四類:

1.基于特定的標志值。

2.根據兩個操作數是否相等,或根據(ECX的值的。

3.基于無符號操作數的比較結果的。

4.基于有符號操作數的比較結果的。

下表列出了基于特定CPU標志:零標志、進位標志、溢出標志、奇偶標志和符號標志的跳轉指令。

基于恒等性比較的跳轉指令

????下表列出了基于兩個操作數是否相等或CX,EXC值是否為零的跳轉指令。

CMP leftOp ,rightOp


JE指令和JZ指令是等價的,JNZ指令和JNE指令時等價的。

基于無符號數比較的跳轉指令

?

基于有符號數比較的跳轉指令

?

6.3.4 ?條件跳轉的應用

測試狀態位

? ? ANDORCMPNOTTEST指令后面常跟能夠改變程序流程的條件跳轉指令,條件跳轉指令通常要測試CPU狀態標志位的值。例如,假設8位的內存操作數status中存放著同計算機相連的外部設備信息,下面的指令在位5置位時跳轉到某標號處,表示機器處于脫機狀態:

mov ?al ,status

test ?al,00100000b ?;測試位5

jnz ??EquipOffline

? ? 下面的語句在位014中的任何一位置位時跳轉到另一個標號處:

mov ?al ,status

test ?al ,00010011b ??;測試位0,1,4

jnz ??InputDataByte

? ? 如果想在2,3,7全部置位時跳轉某標號處,需要使用ANDCMP兩條指令:

mov ??al ,status

and ??al ,10001100b

cmp ??al ,10001100b

je ????ResetMachine

? ? 取兩個整數中的較大的值:下面的指令比較AXBX中的無符號整數并把其中的較大者送DX寄存器:

mov ?dx ,ax ???;假設AX較大

cmp ?ax ,bx

jae ??L1 ??????;如果A>=B 就直接跳轉到L1,否則就把較大的值B放到結果dx

mov ?dx ,bx

L1:

? ? 取三個整數中的較小值:下面的指令比較V1,V2V3三個無符號變量的值,并把其中的最小者送至AX寄存器:

.data

V1 WORD ?

V2 WORD ?

V3 WORD ?

.code

??mov ?ax ,V1 ?;假設V1是最小的

??cmp ?ax ,V2

??jbe ??L1 ????;小于等于則跳轉

??mov ?ax ,V2

L1: cmp ax ,V3

??jbe ??L2 ??

??mov ?ax ,V3

L2:


? ? 應用:數組的順序查找

? ? 在數組中找到第一個非零值。

?

應用:字符串加密(XOR

TITLE Ecnryption Program ???(Encrypt.asm)

INCLUDE Irvine32.inc

KEY = 239

BUFMAX = 128

.data

sPrompt ?BYTE ?"Enter the plain text:" ,0

sEncrypt BYTE ?"Cipher text: ????????" ,0

sDecrypt BYTE ?"Decrypted: ??????????" ,0

buffer ??BYTE ?BUFMAX+1 DUP(0)

bufSize ?DWORD ?

.code

main PROC

????call ?InputTheString

call ?TranslateBuffer

mov ??edx ,OFFSET sEncrypt

call ?DisplayMessage

call ?TranslateBuffer

mov ??edx ,OFFSET sDecrypt

call ?DisplayMessage

exit

main ENDP

?

;-----------------------------------

InputTheString PROC

;

;Prompts user for a plaintext string.Saves the string

;and its length

;Receives:nothing

;Returns: nothing

;-----------------------------------

????pushad

mov ???edx ,OFFSET sPrompt

call ??WriteString

mov ???ecx ,BUFMAX

????mov ???edx ,OFFSET buffer

call ??ReadString

mov ???bufSize ,eax

call ??Crlf

popad

ret

InputTheString ENDP

?

;-----------------------------------

DisplayMessage PROC

;

;Display the ecnrypted or decrypted message.

;Receives :EDX points to the message

;Returns ?:nothing

;-----------------------------------

????pushad

call ?WriteString

mov ??edx ,OFFSET buffer

call ?WriteString

call ?Crlf

call ?Crlf

popad

ret

DisplayMessage ENDP

?

;-----------------------------------

TranslateBuffer ?PROC

;

;Translates the string by exclusive-ORing each

;byte with the encryption key buye.

;Receives :nothing

;Returns ?:nothing

????pushad

mov ecx ,bufSize

mov esi ,0

L1:

????xor ?buffer[esi] ,KEY

inc ?esi

loop L1

popad

ret

TranslateBuffer ENDP

END main


6.3.5 ?位測試指令

BT ,BTC ,BTRBTS指令統稱為位測試(bit testing)指令,這些指令很重要,因為他們可以在單挑院子指令內執行很多個步驟。為測試指令對多線程程序非常有用,對多線程程序而言,在不冒被其他線程中斷的危險的情況下對重要的標志(稱為信號量)進行測試、清除、設置或求反是非常重要的。

BT指令

BT(位測試,bit test)指令選擇第一個操作數位n并把它復制到進位標志中:

BT bitBase,n

第一個操作數成為位基(bitBase,它不會被指令所修改。BT指令允許以下類型操作數:

BT ?r/m16 ,r16

BT ?r/m32 ,r32

BT ?r/m16 ,imm8

BT ?r/m32 ,imm8

在下例中,進位標志等于變量semaphone第七位的值:

.data

semaphone WORD 10001000b

.code

BT ?semaphone ,7 ?????;CF = 1

Intel指令集引入BT指令之前,我們不得不把變量復制到寄存器中,然后再通過移位把第7位送到進位標志中:

mov ?ax ,semaphone

shr ??ax ,8 ????????;CF = 1

BTC指令

BTC(位測試并取反,bit test and complement)指令選擇第一個操作數的位n并把它復制到標志位中,同時對位n取反。

BTR指令

BTR(位測試并復位,bit test and reset)指令選擇第一個操作數位n并把它復制到進位標志中,同時位n清零。

BTS指令

BTS指令(位測試并置位,bit test and set)指令選擇第一個操作數的位n并把它復制到進位標志中,同時位n置位。

6.4 ?條件循環指令

? ? LOOPZLOOPE指令:ecx大于0,并且零標志位置位則循環。

? ? LOOPNZLOOPNE指令:ecx大于0,并且零標志位復位則循環。

6.5 ?條件結構

? ? 條件結構可認為是在不同的邏輯分支之間引發選擇的一個或多個條件表達式,每個分支都會執行不同的指令序列。

6.5.1 ?IF塊結構語句

? ? 這節不想細總結了,書上很大的篇幅就是為了解釋用cmpj*來對應解釋高級語言里那些IF語句什么的。沒什么新東西。

6.5.2 ?復合表達式

? ? 這節是說在高級語言中的類似if(A And B) [A&&B] if(A OR B) [A||B]等在匯編里怎么對應翻譯,其實比較簡單,比如A&&B 可以判斷A滿足然后跳轉到B繼續判斷,有一個不滿足那么直接jmp到其他地方,A||B的話就是先判斷A,如果滿足 那么jmp到滿足,否則判斷B如果滿足那么jmp到滿足,否則jmp到不滿足,這樣也就明白了為什么在高級語言中 a = 0 ,b = 0 ?if(++a || ++b)..之后b沒有被自加的原因(a = 1 ,b = 0)。比較簡單,這一節也不細總結了。

6.5.3 ?WHILE循環

????...這節是說高級語言中的while怎么解析成匯編,比較簡單,我們直接mark一個地方,然后滿足條件就直接往上跳回去就行了,如果不滿足那么就不跳,這樣就自動往下執行,相當于while完了,當然也可以增加其他cmp,j*指令實現break等。

?

6.5.4 ?以表格驅動的分支選擇

? ? 原理是對于多層條件語句嵌套那種,翻譯成匯編會很亂,很麻煩,同時如果我們用匯編開發過程中出現了太多層的條件嵌套寫著也麻煩,有一種方法是我們把每個條件和執行地址看成一個”結構體”,然后在創建一個”結構體數組”,例如

?

? ? 條件A執行00000120處的函數,或者跳轉到那里,條件B則是00000130...這樣我們每次只要線性掃描這個表就行了,這個姿勢叫做以表格驅動的分支選擇。

例子程序:用戶從鍵盤輸入一個字符,程序使用一個循環將該字符同表中每個項比較,對于找到的第一個匹配項,緊跟在待查找值其后存儲的過程將被調用。每個過程使用EDX來裝入不同的字符串偏移,然后在循環中顯示該字符串:

TITLE Table of Procedure Offsets (ProcTable.asm)

;This program contains a table with offsets of procedures.

;It uses the table to execute indirect procedure calls.

INCLUDE Irvine32.inc

.data

CaseTable BYTE ??'A'

??????????DWORD ?Process_A

EntrySize = ($ - CaseTable)

??BYTE ??'B'

??????????DWORD ?Process_B

??BYTE ??'C'

??????????DWORD ?Process_C

??BYTE ??'D'

??????????DWORD ?Process_D

NumberOfEntries = ($ - CaseTable) / EntrySize

prompt ???BYTE ??"Press capital A,B,Cor D:" ,0

msgA ?????BYTE ??"Process_A" ,0

msgB ?????BYTE ??"Process_B" ,0

msgC ?????BYTE ??"Process_C" ,0

msgD ?????BYTE ??"Process_D" ,0

.code

main PROC

????mov ??edx ,OFFSET prompt

call ?WriteString

call ?ReadChar

mov ??ebx ,OFFSET CaseTable

mov ??ecx ,NumberOfEntries

L1:

????cmp ??al ,[ebx]

jne ??L2

call ?NEAR PTR [ebx + 1]

call ?WriteString

call ?Crlf

jmp ??L3

L2:

????add ??ebx ,EntrySize

loop ?L1

L3:

?????exit

main ENDP

?

Process_A PROC

????mov ?edx ,OFFSET msgA

ret

Process_A ENDP

Process_B PROC

????mov ?edx ,OFFSET msgB

ret

Process_B ENDP

Process_C PROC

????mov ?edx ,OFFSET msgC

ret

Process_C ENDP

Process_D PROC

????mov ?edx ,OFFSET msgD

ret

Process_D ENDP

END main

?

?

同時上面有幾個個地方需要注意一下:

1.一個是函數名字直接可以當變量用了:

?

2.A=B不占用.data定義東西的時候的地址空間(不然的話,上面那么寫代碼就算錯了)

?

3.CALL指令調用存儲在EBX+1內存地質處的過程地址,這種間接調用格式要使用NEAR PTR運算符。

?

?

總結

以上是生活随笔為你收集整理的Intel汇编语言程序设计学习-第六章 条件处理-中的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。