最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

5.12 匯編語言:仿寫While循環(huán)語句

2023-08-24 10:23 作者:bili_42682284418  | 我要投稿

循環(huán)語句(While)一種基本控制結(jié)構(gòu),它允許程序在條件為真的情況下重復(fù)執(zhí)行一段代碼塊,直到條件為假為止。循環(huán)語句在處理需要重復(fù)執(zhí)行的任務(wù)時非常有用,它可以讓程序更加高效地處理大量數(shù)據(jù)或者重復(fù)性操作。


一般來說,While循環(huán)由一個條件表達式、一個代碼塊組成。在每次循環(huán)迭代開始時,程序會首先檢查條件表達式的值,如果為真,則執(zhí)行代碼塊,然后再次檢查條件表達式的值。只要條件表達式為真,循環(huán)就會一直繼續(xù)執(zhí)行;一旦條件表達式為假,循環(huán)將停止,程序繼續(xù)執(zhí)行循環(huán)之后的代碼。


### 12.12 Do-While 循環(huán)結(jié)構(gòu)優(yōu)化


DO語句先執(zhí)行循環(huán)體,后進行判斷,如果通過則跳轉(zhuǎn)到循環(huán)體首部繼續(xù)執(zhí)行,未通過則直接順序向下走。DO循環(huán)效率最高,該循環(huán)在結(jié)構(gòu)上非常精簡,利用了程序執(zhí)行時由低到高的特性,由于結(jié)構(gòu)內(nèi)只在結(jié)尾處做了判斷,只使用了一條判斷語句即實現(xiàn)了循環(huán),因此已經(jīng)無需在結(jié)構(gòu)上進行任何優(yōu)化了。


```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


.data

? count DWORD ?

.code

? main PROC

? ? mov dword ptr ds:[count],0? ? ?; 初始化循環(huán)次數(shù)

? S1:

? ? xor eax,eax? ? ? ? ? ? ? ? ? ? ; 執(zhí)行循環(huán)體

? ? mov eax,dword ptr ds:[count]? ?; 取出計數(shù)器

? ? add eax,1? ? ? ? ? ? ? ? ? ? ? ; 遞增

? ? mov dword ptr ds:[count],eax? ?; 回寫

? ??

? ? cmp dword ptr ds:[count],10? ? ; 與10做對比

? ? jl S1? ? ? ? ? ? ? ? ? ? ? ? ? ; 小于則繼續(xù)循環(huán)


? ? int 3

? ? invoke ExitProcess,0

? main ENDP

END main

```


### 12.13 While 循環(huán)結(jié)構(gòu)優(yōu)化


While語句先判斷循環(huán)條件,后執(zhí)行循環(huán)體,由于需要判斷,該循環(huán)的構(gòu)建需要使用兩個跳轉(zhuǎn)語句方可實現(xiàn)。While循環(huán)結(jié)構(gòu)的效率要比Do循環(huán)結(jié)構(gòu)低,While循環(huán)結(jié)構(gòu)先比較再循環(huán),因此無法利用程序執(zhí)行順序來完成循環(huán),又因為While循環(huán)結(jié)構(gòu)使用了2個跳轉(zhuǎn)指令,在程序流程上就弱于Do循環(huán)。


```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


.data

? count DWORD ?

.code

? main PROC

? ? mov dword ptr ds:[count],0? ? ? ? ? ? ; 設(shè)置while初始化

? S1:

? ? cmp dword ptr ds:[count],10? ? ? ? ? ?; 設(shè)置最大循環(huán)數(shù)

? ? jge loop_end? ? ? ? ? ? ? ? ? ? ? ? ? ; 判斷是否循環(huán)結(jié)束

? ??

? ? xor eax,eax? ? ? ? ? ? ? ? ? ? ? ? ? ?; 執(zhí)行循環(huán)體

? ??

? ? mov eax,dword ptr ds:[count]? ? ? ? ? ?; 取出循環(huán)條件

? ? add eax,1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; 遞增

? ? mov dword ptr ds:[count],eax? ? ? ? ? ?; 寫回

? ? jmp S1

??

? loop_end:

? ? int 3


? ? invoke ExitProcess,0

? main ENDP

END main

```

為了提升While循環(huán)執(zhí)行效率,編譯器通常會將其轉(zhuǎn)換為對等的Do循環(huán),如果循環(huán)無法轉(zhuǎn)成對等的Do循環(huán),則可使用單層IF結(jié)構(gòu)內(nèi)部嵌套Do循環(huán)的方式來實現(xiàn),外層IF則用來判斷Do循環(huán)是否執(zhí)行,例如如下案例中,首先外層使用IF語句判斷循環(huán)條件,該語句內(nèi)部則嵌套一個Do循環(huán),以此來將While轉(zhuǎn)為Do。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


.data

? count DWORD ?

.code

? main PROC

? ? mov dword ptr ds:[count],0? ? ? ? ? ? ; 設(shè)置初始條件

? ??

? ? ; 初次判斷條件是否滿足

? ? cmp dword ptr ds:[count],10

? ? jge loop_end

? S1:

? ? ; 循環(huán)體內(nèi)部語句

? ? xor eax,eax

? ??

? ? ; 遞增

? ? add dword ptr ds:[count],1

? ??

? ? ; 比較條件是否滿足

? ? cmp dword ptr ds:[count],10

? ? jl S1

? ??

? loop_end:

? ? int 3


? ? invoke ExitProcess,0

? main ENDP

END main

```


### 12.15 Loop 循環(huán)結(jié)構(gòu)優(yōu)化


上方提到過的三種循環(huán)模式都是通過跳轉(zhuǎn)指令與計數(shù)器構(gòu)建的,與這三者不同匯編中默認提供了loop指令,專門用來實現(xiàn)循環(huán)計數(shù)功能,由于是匯編指令,所以此loop語句必須讀入ECX寄存器內(nèi)的次數(shù)作為循環(huán)終止條件,每次讀入會自動遞減,具體匯編代碼如下。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


.data

? count DWORD ?

? result DWORD ?

? ArrayDW DWORD 8,7,9,4,3,7,5,8,9,3,0h


.code

? main PROC

? ? ; 通過loop實現(xiàn)的單層循環(huán)體

? ? xor eax,eax? ? ? ? ? ? ? ? ? ? ? ?; 用于累加數(shù)據(jù)

? ? mov ecx,10? ? ? ? ? ? ? ? ? ? ? ? ; 設(shè)置循環(huán)次數(shù)

? s1:

? ? mov dword ptr ds:[count],ecx? ? ? ; 將循環(huán)次數(shù)備份

? ? xor ecx,ecx? ? ? ? ? ? ? ? ? ? ? ?; 清空寄存器

? ? mov ecx,10

? ? add eax,ecx? ? ? ? ? ? ? ? ? ? ? ?; 結(jié)果想加到eax

? ? mov ecx,dword ptr ds:[count]? ? ? ; 恢復(fù)循環(huán)次數(shù)

? ? loop s1

? ??

? ? mov dword ptr ds:[result],eax? ? ?; 獲取相加后的結(jié)果

? ??

? ? invoke ExitProcess,0

? main ENDP

END main

```

如果是雙層循環(huán)體,則在使用loop語句構(gòu)建時,必須考慮外層ECX中的循環(huán)計數(shù)該如何處理,通常會把外層循環(huán)計數(shù)保存在棧中,這是非常的理想的,保存在一個變量內(nèi)也勉強湊活,只是效率上沒有直接壓入棧中高。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


.data

? count DWORD ?

? result DWORD ?

? ArrayDW DWORD 8,7,9,4,3,7,5,8,9,3,0h


.code

? main PROC

? ? ; 通過loop實現(xiàn)嵌套循環(huán)體

? ? mov ecx,9? ? ? ? ? ? ? ? ? ?; 控制外層循環(huán)數(shù)

? s2:

? ? push ecx? ? ? ? ? ? ? ? ? ? ; 保存外層循環(huán)數(shù)

? ? mov ecx,9? ? ? ? ? ? ? ? ? ?; 設(shè)置內(nèi)層循環(huán)數(shù)

? s3:

? ? mov eax,dword ptr ds:[ArrayDW + ecx * 4]

? ? cmp eax,3? ? ? ? ? ? ? ? ? ? ; 與3作比較大于則跳

? ? ja jump

? ? loop s3

? jump:

? ? xor eax,eax

? ? pop ecx

? ? loop s2

? ??

? ? invoke ExitProcess,0

? main ENDP

END main

```

運用Loop指令實現(xiàn)對數(shù)組`MyArray`的由大到小排序,其中`ArraySort`子過程用于由大到小排序,子過程`PrintArray`用于循環(huán)輸出排序后的結(jié)果。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? MyArray DWORD 25,74,89,33,24,67,93,15,78,92

? Count DWORD 10

? PrCount DWORD ?

? szFmt BYTE '%d ',0dh,0ah,0


.code

? ; 數(shù)組排序函數(shù)

? ArraySort PROC

? ? ? mov ecx,dword ptr ds:[Count]? ? ? ; 獲取到數(shù)組元素數(shù)

? ? ? dec ecx? ? ? ? ? ? ? ? ? ? ? ? ? ?; 數(shù)組減1

? ? L1:

? ? ? push ecx? ? ? ? ? ? ? ? ? ? ? ? ? ; 入棧保存

? ? ? lea esi,dword ptr ds:[MyArray]? ? ; 得到數(shù)組基地址

? ? ??

? ? L2:

? ? ? mov eax,dword ptr ds:[esi]

? ? ? cmp eax,dword ptr ds:[esi + 4]? ? ; 比較第一個數(shù)組與第二個

? ? ? jg L3

? ? ??

? ? ? xchg eax,[esi + 4]? ? ? ? ? ? ? ? ; 交換數(shù)據(jù)

? ? ? mov [esi],eax

? ? L3:

? ? ? add esi,4

? ? ? loop L2

? ? ??

? ? ? pop ecx? ? ? ? ? ? ? ? ? ? ? ? ? ?; 彈出數(shù)據(jù)

? ? ? loop L1

? ? ? ret

? ArraySort ENDP

??

? ; 循環(huán)輸出元素

? PrintArray PROC

? ? ? mov dword ptr ds:[PrCount],0? ? ? ? ? ? ; 初始化元素

? ? ??

? ? L1:

? ? ? mov ecx,dword ptr ds:[PrCount]? ? ? ? ? ; 獲取循環(huán)次數(shù)

? ? ? cmp ecx,10? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; 對比十次

? ? ? jge lop_end? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; 判斷是否可結(jié)束循環(huán)

? ? ??

? ? ? lea eax,dword ptr ds:[MyArray]? ? ? ? ? ; 獲取數(shù)組基地址

? ? ? mov ebx,dword ptr ds:[eax + ecx * 4]? ? ; 比例因子尋址

? ? ? invoke crt_printf,addr szFmt,ebx

? ? ??

? ? ? mov ecx,dword ptr ds:[PrCount]? ? ? ? ? ; 取循環(huán)計數(shù)

? ? ? add ecx,1

? ? ? mov dword ptr ds:[PrCount],ecx? ? ? ? ? ; 遞增后回寫

? ? ? jmp L1

? ? ??

? ? lop_end:

? ? ? int 3

? ? ? ret


? PrintArray ENDP


? main PROC

? ? invoke ArraySort

? ? invoke PrintArray

? main ENDP

END main

```


### 12.16 仿寫Do-While循環(huán)體


這段C++代碼定義了一個包含10個元素的整型數(shù)組,然后在do-while循環(huán)中對數(shù)組進行遍歷,并檢查每一個數(shù)組元素是否滿足下面的條件:它的值大于10并且下一個數(shù)組元素的值小于等于20。如果找到了滿足條件的數(shù)組元素,則輸出它和下一個數(shù)組元素的值,并跳出循環(huán)。如果循環(huán)結(jié)束都沒有找到符合條件的數(shù)組元素,則直接退出程序。這段代碼展示了如何使用循環(huán)和條件判斷對數(shù)組進行遍歷和篩選。


```C

#include <stdio.h>

#include <Windows.h>


int main(int argc, char *argv[])

{

? int Array[10] = { 56,78,33,45,78,90,32,15,56,67 };

? int index = 0;


? do

? {

? ? if (Array[index] > 10 && Array[index + 1] <= 20)

? ? {

? ? ? printf("array[1] => %d array[2] => %d \n", Array[index], Array[index + 1]);

? ? ? break;

? ? }


? ? index = index + 1;

? } while (index < 10);


? system("pause");

? return 0;

}

```

由于是自己仿寫,所以此處我使用了For形式的循環(huán)模式,首先初始化`count=0`進入L1循環(huán)后先來判斷數(shù)組中第一個元素是否小于10,接著通過`add eax,1`將比例因子向后移動4字節(jié),繼續(xù)比較第二個數(shù)值是否小于等于20,如果都存在則直接輸出該結(jié)果,并通過`jmp lop_end`跳轉(zhuǎn)到程序結(jié)尾,否則遞增`count`元素,并跳轉(zhuǎn)到循環(huán)開頭繼續(xù)查找。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? MyArray DWORD 56,78,33,45,78,90,32,15,56,67

? count DWORD ?

? szFmt BYTE 'array[1] => %d array[2] => %d ',0dh,0ah,0


.code

? main PROC

? ? mov dword ptr ds:[count],0? ? ? ? ? ? ? ? ? ? ?; int index = 0;


? L1:

? ? mov eax,dword ptr ds:[count]

? ? cmp dword ptr ds:[MyArray + eax * 4],10? ? ? ? ; Array[index] > 10

? ? jle L2

? ??

? ? mov eax,dword ptr ds:[count]

? ? add eax,1

? ? cmp dword ptr ds:[MyArray + eax * 4],20? ? ? ? ; Array[index + 1] <= 20

? ? jg L2

? ??

? ? mov esi,dword ptr ds:[MyArray + eax * 4 - 4]? ?; esi = Array[index]

? ? mov edi,dword ptr ds:[MyArray + eax * 4]? ? ? ?; edi = Array[index+1]

? ? invoke crt_printf,addr szFmt,esi,edi

? ? jmp lop_end? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; break


? L2:

? ? mov eax,dword ptr ds:[count]

? ? add eax,1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; index = index + 1;

? ? mov dword ptr ds:[count],eax

? ? cmp dword ptr ds:[count],10? ? ? ? ? ? ? ? ? ? ; index < 10

? ? jl L1


? lop_end:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; break

? ? int 3

? main ENDP

END main

```


### 12.17 仿寫While循環(huán)體


這段C++代碼定義了一個包含10個元素的整型數(shù)組,然后在while循環(huán)中對數(shù)組進行遍歷,輸出每一個數(shù)組元素的值。循環(huán)使用一個count變量作為計數(shù)器,從0開始逐步增加,直到count的值等于數(shù)組元素的總數(shù)。在循環(huán)內(nèi)部,它通過count變量訪問數(shù)組元素,并將它們的值作為參數(shù)傳遞給printf函數(shù)進行輸出。這段代碼展示了如何使用循環(huán)結(jié)構(gòu)遍歷數(shù)組元素。


```C

#include <stdio.h>

#include <Windows.h>


int main(int argc,char *argv[])

{

? int Array[10] = { 1,2,3,4,5,6,7,8,9,10 };

? int count = 0;


? while (count < sizeof(Array) / sizeof(int))

? {

? ? printf("value = %d \n", Array[count]);

? ? count = count + 1;

? }

? return 0;

}

```

首先初始化部分,設(shè)置`ecx寄存器`為比例因子,進入循環(huán)體后,通過尋址公式`ds:[esi + ecx * 4]`實現(xiàn)對數(shù)組地址的遞增輸出,此代碼中的`ds:[count]`只用于控制循環(huán)體循環(huán)次數(shù),`ecx寄存器`則只用做尋址因子使用。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? MyArray DWORD 1,2,3,4,5,6,7,8,9,10

? count DWORD ?

? szFmt BYTE 'value = %d ',0dh,0ah,0

.code

? main PROC

? ? mov dword ptr ds:[count],0? ? ? ? ? ? ? ? ?; 初始化循環(huán)

? ? mov ecx,0? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; 設(shè)置循環(huán)計數(shù)(比例因子)


? S1:

? ? cmp dword ptr ds:[count],lengthof MyArray? ; 與數(shù)組總長度對比

? ? jge lop_end? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; 是否結(jié)束

? ??

? ? lea esi,dword ptr ds:[MyArray]? ? ? ? ? ? ?; 獲取數(shù)組基地址

? ? mov ebx,dword ptr ds:[esi + ecx * 4]? ? ? ?; 比例因子尋址

? ? invoke crt_printf,addr szFmt,ebx? ? ? ? ? ?; 調(diào)用系統(tǒng)crt

? ??

? ? mov ecx,dword ptr ds:[count]

? ? add ecx,1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; 計次循環(huán)遞增

? ? mov dword ptr ds:[count],ecx

? ? jmp S1


? lop_end:

? ? int 3

? ? invoke ExitProcess,0

? main ENDP

END main

```


### 12.18 仿寫While三層循環(huán)體


這段C++代碼實現(xiàn)了一個三重循環(huán),用于生成所有由1到4中不重復(fù)的三個數(shù)字組成的序列。在外層循環(huán)中,它使用變量x從1開始逐個增加,直到其值大于等于5。在中間循環(huán)中,它使用變量y從1開始逐個增加,直到其值大于等于5。在最內(nèi)層循環(huán)中,它使用變量z從1開始逐個增加,直到其值大于等于5。然后它檢查當(dāng)前的x、y、z變量是否滿足三個數(shù)不重復(fù)的條件,如果滿足,則輸出這三個數(shù)字,并進入第三個循環(huán)。循環(huán)結(jié)構(gòu)使用變量z逐項增加,并在檢查條件后繼續(xù)下一個序列的生成。當(dāng)z逐項增加完成后,中間循環(huán)使用變量y逐項增加。如此循環(huán),直到所有由1到4的三個數(shù)字序列都被產(chǎn)生出來為止。


```C

#include <windows.h>

#include <stdio.h>


int main(int argc,char * argv[])

{

? int x=1, y=1, z=1;


? while (x < 5)

? {

? ? while (y < 5)

? ? {

? ? ? while (z < 5)

? ? ? {

? ? ? ??

? ? ? ? if (x != z && x != y && y != z)

? ? ? ? {

? ? ? ? ? printf("%d,%d,%d \n", x, y, z);

? ? ? ? }

? ? ? ? z = z + 1;

? ? ? }

? ? ? z = 1;

? ? ? y = y + 1;

? ? }

? ? y = 1;

? ? x = x + 1;

? }

? return 0;

}

```

由于這段C代碼使用了`三層While`循環(huán),其構(gòu)建為匯編代碼時稍有些難度,我們首先把外層框架構(gòu)建好,先來構(gòu)建一個`二層While循環(huán)`結(jié)構(gòu),如下匯編代碼中,我們通過變量`x DWORD`控制外層循環(huán)次數(shù),內(nèi)層循環(huán)次數(shù)則使用`y DWORD`變量來控制,當(dāng)每次需要修改或讀取變量時,則通過`mov ecx,dword ptr ds:[x]`指令將計數(shù)次數(shù)讀入到`ecx寄存器`內(nèi),以此來保證循環(huán)次數(shù)不沖突。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? x DWORD ?

? y DWORD ?

? szFmt BYTE '外層循環(huán): %d ---> 內(nèi)層循環(huán):%d ',0dh,0ah,0


.code

? main PROC

? ? mov dword ptr ds:[x],1? ? ? ? ? ?; x = 1

??

? ? ; 外層循環(huán)

? L1:

? ? mov ecx,dword ptr ds:[x]

? ? cmp ecx,5? ? ? ? ? ? ? ? ? ? ? ? ; x < 5

? ? jge lop_end

? ??

? ? ; 內(nèi)層循環(huán)

? ? mov dword ptr ds:[y],1? ? ? ? ? ?; y = 1

? ??

? L2:

? ? mov ecx,dword ptr ds:[y]? ? ? ? ?; ecx = y

? ? cmp ecx,5? ? ? ? ? ? ? ? ? ? ? ? ; y < 5

? ? jge L3

? ??

? ? ; 循環(huán)過程執(zhí)行(存放循環(huán)過程代碼)

? ? mov esi,dword ptr ds:[x]

? ? mov edi,dword ptr ds:[y]

? ? invoke crt_printf,addr szFmt,esi,edi


? ? mov ecx,dword ptr ds:[y]

? ? add ecx,1? ? ? ? ? ? ? ? ? ? ? ? ; y = y + 1

? ? mov dword ptr ds:[y],ecx

? ? jmp L2


? L3:

? ? mov ecx,dword ptr ds:[x]

? ? add ecx,1? ? ? ? ? ? ? ? ? ? ? ? ; x = x + 1

? ? mov dword ptr ds:[x],ecx

? ? jmp L1

??

? lop_end:

? ? int 3?


? main ENDP

END main

```

既然二層結(jié)構(gòu)可以被構(gòu)建出來,那么我們利用這個原理,在二層基礎(chǔ)之上增加一個`z DWORD`變量,用于對最內(nèi)部的`While`語句進行計數(shù),由此我們就可以構(gòu)建出`三層While循環(huán)`結(jié)構(gòu),匯編代碼如下所示,仔細看完全能看懂的。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? x DWORD ?

? y DWORD ?

? z DWORD ?

? szFmt BYTE '外層循環(huán): %d ---> 中間層循環(huán): %d ---> 內(nèi)層循環(huán): %d? ',0dh,0ah,0


.code

? main PROC

? ? mov dword ptr ds:[x],1? ? ? ? ? ?; x = 1

??

? ? ; 外層循環(huán)

? L1: mov ecx,dword ptr ds:[x]

? ? cmp ecx,5? ? ? ? ? ? ? ? ? ? ? ? ; x < 5

? ? jge lop_end

? ??

? ? ; 中間循環(huán)

? ? mov dword ptr ds:[y],1? ? ? ? ? ?; y = 1

? L2: mov ecx,dword ptr ds:[y]? ? ? ? ?; ecx = y

? ? cmp ecx,5? ? ? ? ? ? ? ? ? ? ? ? ; y < 5

? ? jge L3? ? ? ? ? ? ? ? ? ? ? ? ? ?; 大于跳到最外層


? ? ; 內(nèi)層循環(huán)

? ? mov dword ptr ds:[z],1? ? ? ? ? ?; z = 1

? ??

? L5: mov ecx,dword ptr ds:[z]

? ? cmp ecx,5? ? ? ? ? ? ? ? ? ? ? ? ; z < 5

? ? jge L4? ? ? ? ? ? ? ? ? ? ? ? ? ?; 大于跳到中間層

? ??

? ? ; 三層循環(huán)框架

? ? mov eax,dword ptr ds:[x]

? ? mov ebx,dword ptr ds:[y]

? ? mov ecx,dword ptr ds:[z]

? ? invoke crt_printf,addr szFmt,eax,ebx,ecx

? ??

? ? mov ecx,dword ptr ds:[z]

? ? add ecx,1? ? ? ? ? ? ? ? ? ? ? ? ?; z = z + 1

? ? mov dword ptr ds:[z],ecx

? ??

? ? jmp L5

? ??

? L4: mov ecx,dword ptr ds:[y]

? ? add ecx,1? ? ? ? ? ? ? ? ? ? ? ? ; y = y + 1

? ? mov dword ptr ds:[y],ecx

? ? jmp L2


? L3: mov ecx,dword ptr ds:[x]

? ? add ecx,1? ? ? ? ? ? ? ? ? ? ? ? ; x = x + 1

? ? mov dword ptr ds:[x],ecx

? ? jmp L1

??

? lop_end:

? ? int 3?


? main ENDP

END main

```

最后我們用上方三層結(jié)構(gòu)作為框架使用,在其基礎(chǔ)之上增加內(nèi)部的IF判斷功能實現(xiàn),這樣一來我們的三層While嵌套循環(huán)體的仿寫就實現(xiàn)了,多說一句,在仿寫時一定要注意次序跟規(guī)律謹慎些,寫出來并不難。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? x DWORD ?

? y DWORD ?

? z DWORD ?

? szFmt BYTE '%d,%d,%d ',0dh,0ah,0


.code

? main PROC

? ? mov dword ptr ds:[x],1? ? ? ? ? ?; x = 1

??

? ? ; 外層循環(huán)

? L1: mov ecx,dword ptr ds:[x]

? ? cmp ecx,5? ? ? ? ? ? ? ? ? ? ? ? ; x < 5

? ? jge lop_end

? ??

? ? ; 中間循環(huán)

? ? mov dword ptr ds:[y],1? ? ? ? ? ?; y = 1

? L2: mov ecx,dword ptr ds:[y]? ? ? ? ?; ecx = y

? ? cmp ecx,5? ? ? ? ? ? ? ? ? ? ? ? ; y < 5

? ? jge L3? ? ? ? ? ? ? ? ? ? ? ? ? ?; 大于跳到最外層


? ? ; 內(nèi)層循環(huán)

? ? mov dword ptr ds:[z],1? ? ? ? ? ?; z = 1

? ??

? L5: mov ecx,dword ptr ds:[z]

? ? cmp ecx,5? ? ? ? ? ? ? ? ? ? ? ? ; z < 5

? ? jge L4? ? ? ? ? ? ? ? ? ? ? ? ? ?; 大于跳到中間層

? ??

? ? ; 三層循環(huán)框架

? ? ;mov eax,dword ptr ds:[x]

? ? ;mov ebx,dword ptr ds:[y]

? ? ;mov ecx,dword ptr ds:[z]

? ? ;invoke crt_printf,addr szFmt,eax,ebx,ecx

? ??

? ? ; 開始在框架中搞事情

? ? mov eax,dword ptr ds:[x]

? ? cmp eax,dword ptr ds:[z]

? ? je L6

? ? mov eax,dword ptr ds:[x]

? ? cmp eax,dword ptr ds:[y]

? ? je L6

? ? mov eax,dword ptr ds:[y]

? ? cmp eax,dword ptr ds:[z]

? ? je L6

? ??

? ? invoke crt_printf,addr szFmt,dword ptr ds:[x],dword ptr ds:[y],dword ptr ds:[z]

? ??

? L6: mov ecx,dword ptr ds:[z]

? ? add ecx,1? ? ? ? ? ? ? ? ? ? ? ? ?; z = z + 1

? ? mov dword ptr ds:[z],ecx

? ??

? ? jmp L5

? ??

? L4: mov ecx,dword ptr ds:[y]

? ? add ecx,1? ? ? ? ? ? ? ? ? ? ? ? ; y = y + 1

? ? mov dword ptr ds:[y],ecx

? ? jmp L2


? L3: mov ecx,dword ptr ds:[x]

? ? add ecx,1? ? ? ? ? ? ? ? ? ? ? ? ; x = x + 1

? ? mov dword ptr ds:[x],ecx

? ? jmp L1

??

? lop_end:

? ? int 3?


? main ENDP

END main

```


### 12.19 仿寫While實現(xiàn)二分法


該C++代碼實現(xiàn)了一個二分查找算法,用于在已排序的數(shù)組中查找指定值的位置。代碼中定義了一個BinSearch函數(shù),通過對傳入數(shù)組進行二分查找,最終返回要查找的值在數(shù)組中的索引值。main函數(shù)調(diào)用了BinSearch函數(shù),在已知數(shù)組中查找指定值并輸出其在數(shù)組中的索引。


```C

#include <windows.h>

#include <stdio.h>


int BinSearch(int value[], const int SearchVal, int Count)

{

? int first = 0;

? int last = Count - 1;


? while (first <= last)

? {

? ? int mid = (last + first) / 2;? ? ? // 取中位數(shù)

? ? if (value[mid] < SearchVal)? ? ? ? // 中位數(shù)小于searchVal

? ? {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 說明元素在后面

? ? ? first = mid + 1;

? ? }

? ? else if (value[mid] > SearchVal)

? ? {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 否則說明元素在前

? ? ? last = mid - 1;

? ? }

? ? else

? ? { // 找到后返回中位數(shù)

? ? ? return mid;

? ? }

? }

? return -1;

}


int main(int argc, char *argv[])

{

? // 二分查找法,必須針對的是有序數(shù)組

? int Array[10] = { 1,2,3,4,5,6,7,8,9,10 };


? // 查找數(shù)組Array中索引7所在的下標

? int ret = BinSearch(Array, 7, 10);

? printf("數(shù)組下標: %d \n", ret);


? system("pause");

? return 0;

}

```

接著是嘗試使用匯編實現(xiàn)這個查找邏輯,這段代碼你一定可以看懂,細心些就好,我寫的時候也思考了很長時間才寫出來的。

```ASM

? .386p

? .model flat,stdcall

? option casemap:none


include windows.inc

include kernel32.inc

includelib kernel32.lib


include msvcrt.inc

includelib msvcrt.lib


.data

? MyArray DWORD 1,2,3,4,5,6,7,8,9,10

??

? SearchVal DWORD 7

? Count DWORD 10

??

? first DWORD ?

? last DWORD ?

? mid DWORD ?

? szFmt BYTE '%d ',0dh,0ah,0


.code

? main PROC

? ? mov dword ptr ds:[first],0? ? ? ? ?; first = 0;

? ? mov edi,dword ptr ds:[SearchVal]? ?; 得到要查找的數(shù)

? ? lea ebx,dword ptr ds:[MyArray]? ? ?; 得到數(shù)組基地址


? ? ; int last = Count - 1;

? ? mov eax,dword ptr ds:[Count]

? ? sub eax,1

? ? mov dword ptr ds:[last],eax

? ??

? ? ; while(first <=last)

? L1: mov ecx,dword ptr ds:[first]

? ? cmp ecx,dword ptr ds:[last]

? ? jg lop_end

? ??

? ? ; int mid = (last + first) / 2;

? ? mov eax,dword ptr ds:[last]

? ? add eax,dword ptr ds:[first]

? ? shr eax,1

? ? mov dword ptr ds:[mid],eax

? ??

? ? ; edx = value[mid]

? ? mov esi,dword ptr ds:[mid]

? ? shl esi,2

? ? mov edx,[ebx + esi]

? ? ;invoke crt_printf,addr szFmt,edx


? ? ; if(edx < SearchVal(edi))

? ? cmp edx,edi

? ? jge L2

? ? ; first = mid + 1;

? ? mov eax,dword ptr ds:[mid]

? ? add eax,1

? ? mov dword ptr ds:[first],eax

? ? jmp L1

? L2:

? ? ; else if (value[mid] > searchVal)

? ? cmp edx,edi

? ? jle L3

? ? ; last = mid - 1;

? ? mov eax,dword ptr ds:[mid]

? ? sub eax,1

? ? mov dword ptr ds:[last],eax

? ? jmp L1

??

? L3: ; else

? ? mov eax,dword ptr ds:[mid]

? ? invoke crt_printf,addr szFmt,eax

? ? jmp lop_end

? ? jmp L1

? lop_end:

? ? mov eax,-1

? ? int 3


? main ENDP

END main

```


本文作者: 王瑞

本文鏈接: https://www.lyshark.com/post/910678b8.html

版權(quán)聲明: 本博客所有文章除特別聲明外,均采用 BY-NC-SA 許可協(xié)議。轉(zhuǎn)載請注明出處!


5.12 匯編語言:仿寫While循環(huán)語句的評論 (共 條)

分享到微博請遵守國家法律
建德市| 华宁县| 扎鲁特旗| 凉山| 洞口县| 合作市| 台州市| 吴江市| 新源县| 商洛市| 长阳| 上饶县| 尼勒克县| 汝州市| 二手房| 天峻县| 津市市| 兴国县| 虎林市| 罗定市| 泽库县| 赤峰市| 阳谷县| 铜川市| 施甸县| 都安| 扶风县| 榆中县| 增城市| 孝义市| 万年县| 泸州市| 山阳县| 平阴县| 聂荣县| 安庆市| 澄迈县| 兴仁县| 林甸县| 白玉县| 阿鲁科尔沁旗|