在高階語言程式設計中,我們不僅要求程式可以順序執行,還要求其可以執行不同分支,或者反覆執行某些操作。在組合語言中,相同具有相同的能力,可以由對應的指令來控制程式的執行流程。由於畢竟高階語言都是彙編實現的,僅僅是不直觀而已。
無條件轉移為
jmp。類似
c語言中的
goto
。 在
c語言中,goto
是不推薦使用的,會使程式難以控制和理解,但在彙編中,沒有對應的
if 和
while
語句。僅僅能使用
jmp來完畢邏輯複雜的控制結構。
jmp分為段內轉移和段間轉移。只是在
windows
程式設計上,乙個**段的大小為4g
b。一般不須要段間轉移。
條件轉移是由
cpu提供多個標誌位,在執行這類指令之前。檢查之前已經設定的標誌位的狀態來決定是否進行轉移。能夠想象,通過條件轉移。能夠實現分支和迴圈。
在彙編中,設計乙個分支結構的思路基本是這種。由條件轉移指令來推斷條件是否滿足,若滿足,則跳過分支程式。否則繼續向下執行,最後會合。
程式
int x = 10;相應的彙編int signx;
int main()
x sdword -45
signx sdword ?
mov signx, 0
cmp x, 0
jz a70 ;為0
jg a60 ;大於0
mov signx, -1
jmp a70
a60:
mov signx, 1
a70:
二分查詢
對於乙個已排序的陣列,最快的查詢乙個元素的方法不是順序查詢。而是二分查詢。這個用
c 語言寫很方便。首先我們還是畫出流程圖,這有助於我們用
jmp轉換之。
陣列為r,元素個數為
n。要查詢的數為
執行過程為:(1
)先設定查詢範圍為下界
l到上界h
(2)假設下界大於上界,且沒查到。則查詢失敗
(3)取下界和上界的中點
m=(l+h)/2
,該數為
r[m]
(4)若該數為
a,則演算法結束
(5)若該數小於
a。則改動下界
l=m+1
,並跳轉到第二步
(6)若該數大於
a,則改動上界
h=m-1
,並跳轉到第二步
彙編源**
.386
.model flat,stdcall
optioncasemap:none
includelib msvcrt.lib
printf proto c :dword, :vararg
.data
darray dword 50, 56, 64, 73, 83, 92, 103, 105
items equ $-darray)/4 ; 陣列長度
index dword ?
count dword ?
szfmt byte 'index=%d count=%d element=%d', 0; 格式化字串
szerr byte 'not found'
l sdword ?
h sdword ? m sdword ? a sdword 83 ; 所查詢的數字 .code start: mov index, -1; mov count, 0 mov l, 0 mov h, items-1; mov ecx, l mov edx, h b10: cmp ecx, edx ; 下界和上界比較 jg b40 ; 超出。則未找到 mov esi, ecx; add esi, edx shr esi, 1 ; m = (l+h)>>1 inc count mov eax, a ; 取出被比較的數 cmp eax, darray[esi*4] ; 取出該數 jz b30 ; 相等 jg b20 ; 比 a 小,改動下界 ; 比 a 大,改動上界 mov edx, esi dec edx ; h = m-1 jmp b10 b20: mov ecx, esi inc ecx ; l = m+1 jmp b10 b30: mov index, esi ; 呼叫 c 庫的 printf invoke printf, offset szfmt, index, count, darray[esi*4] jmp b50 b40: ; 查詢失敗 invoke printf, offset szerr b50: ret end start
有序表插入
首先遍歷陣列。找到
m,滿足
r[m-1]a
。 然後將
r[m..n-1]
每個元素向後移動乙個位置,再插入a。
關鍵部分彙編**
start:
mov eax, element ; 將插入的元素
mov esi, 0 ; 當前比較元素的下標
c10:
cmp darray[esi*4], eax
ja c20
inc esi
cmp esi, items ; 超出陣列長度,
jb c10 ; 沒有超出
;c20:
mov edi, items-1 ; 從陣列尾部開始移動
c30:
cmp edi, esi ; 與插入位置比較
jl c40 ; 移動完畢
; 還沒完畢,繼續移動
mov ebx, darray[edi*4]
mov darray[edi*4+4], ebx ; 向後移動乙個元素
dec edi
jmp c30 ; 繼續推斷。決定是否移動
c40:
mov darray[esi*4], eax ; 移動完畢,插入元素
迴圈實際編碼解決這個問題時,常常遇到大量反覆的動作,利用迴圈結構能夠簡化程式的編寫。
實際在上文中,已經有迴圈部分出現,但那是不定次數的迴圈。
乙個迴圈結構分為三部分:迴圈初始化,迴圈體,迴圈結束控制。
乙個固定次數的迴圈,有
loop
命令來實現。迴圈次數在
ecx中。
階乘這裡直接使用
ecx
作為乘數。其會隨迴圈遞減。正好符合階乘的定義。
.data
fact dword ?
n equ 5
.code
start:
mov ecx, n ; 迴圈初值,同一時候也是乘數初值
mov eax, 1 ; fact 初值
e10:
imul eax, ecx ; 相乘
loop e10
mov fact, eax ; 階乘結果
冒泡冒泡演算法是乙個多重迴圈。
start:
mov ecx, items-1
i10:
xor esi, esi ; 清零
i20:
mov eax, darray[esi*4]
mov ebx, darray[esi*4+4]
cmp eax, ebx ; 比較相鄰的兩個數
jl i30
mov darray[esi*4], ebx ;較大的數在左邊。須要移動
mov darray[esi*4+4], eax ; 須要交換兩個數
; 比較下一對數
i30:
inc esi
cmp esi, ecx
jb i20 ; 內迴圈。一遍下來,最大的數,移到了最右邊
loop i10 ; 外迴圈
參考文獻
[1] 譚毓安, 張雪蘭. windows組合語言程式設計教程. 北京: 電子工業出版社, 2005.
彙編實驗 分支迴圈結構程式練習
一 實驗內容 試編寫程式,完成下面功能 1 程式執行時,顯示提示資訊 please input a string length 9 由使用者輸入乙個長度小於9的字串 2 然後顯示提示資訊 please input the index of the char to display 請使用者指定該串中的...
分支與迴圈(3)
while迴圈 語法 while 條件 執行迴圈體 例 age 23 while age 18 print 成年人 for迴圈語法 for 目標 in 表示式 執行迴圈體 例 range 語法 range start,stop step 1 這個bif有三個引數,其中用括號括起來的兩個表示這兩個引數...
分支與迴圈語句
練習 列印1 100之間的奇數 include include int isodd int x return 1 int main i system pause return 0 侷限性 1.若忘記break,會繼續執行 2.case語句中無法定義變數 3.case語句判定的條件必須是int lon...