Linux彙編教程03:大小比較操作

Linux彙編

我們在上一講中,簡單瞭解了彙編程序大概的樣子。接下來我們來了解一下,彙編程序的大小比較操作。所以我們以編寫尋找一堆數中的最大值作爲學習的載體。

 

在編寫程序之前,先要分析我們的目的,在得出解決方案。

目的:在一堆數中找到最大的數

思路:要實現這個目的,首先,我們一定要對數據進行索引,每一次比較,兩個數應該分別佔用一個寄存器,得到最大值,所以,我們有一個寄存器一定是存放最大值的。一開始沒有最大值,我們不妨設第一個數爲最大值,後面一次索引大小比較。得出最大值。索引中還會用到循環結構。

解決方案——代碼

在代碼之前,先說一下用到的寄存器

%eax – 用來存儲當前數據

%ebx – 用來存儲最大值

%edi – 存儲索引

 

.section .data

data_items:
.long 3, 14, 15, 9, 26, 53, 58, 97, 93, 2, 38, 4, 36, 0

.section .text
.globl _start
_start:
movl $0, %edi
movl data_items( , %edi, 4), %eax
movl %eax, %ebx

start_loop:
cmpl $0, %eax
je loop_exit
incl %edi
movl data_items( , %edi, 4 ), %eax
cmpl %ebx, %eax
jle start_loop
movl %eax, %ebx
jmp start_loop

loop_exit:
movl $1, %eax
int $0x80

alex@lab: ~-assembly_001

把上面的代碼保存爲maximum.s,在編譯鏈接,運行。正常情況下最大應該是97。

Selection_002

現在來具體解釋代碼:

.section .data 爲數據段,前面一節我們提到過。

 

data_items:
.long 3, 14, 15, 9, 26, 53, 58, 97, 93, 2, 38, 4, 36, 0

這是數據段裏面的內容,data_items 是標籤,代表一個地址。在這個位置後面是一堆數字,這些數字的類型是long(長整形,4字節)。而data_items標籤代表的地址就是這段數字的開頭,在這個例子中,data_items對應的地址下的內容爲long類型的數字3。

這個數據項的末尾的0是人爲添加,在這裏來作爲是否到達末尾的判斷依據。

 

movl $0, %edi
movl data_items( , %edi, 4), %eax
movl %eax, %ebx

這裏是爲循環做好準備,我們要把索引寄存器%edi的值變爲0,應爲我們要從數據的第一個數字開始獲取數據。

movl data_items( , %edi, 4), %eax 這句是把數據的第一個數據載入到%eax裏面。
這裏的源操作數是data_items( , %edi, 4),目的操作數是%eax,而源操作數比較複雜,這裏涉及到內存裏的尋址方式。這一點也是彙編中十分重要的內容。我們下一講具體來講解。這裏想講最基本的。在內存中地址引用的通用格式是下面這樣:

地址或偏移(%基址寄存器,%索引寄存器,比例因子)

實際地址 = 地址或偏移 + %基址寄存器 + 比例因子 * %索引寄存器

這裏用到的是索引尋址方式,是利用地址或偏移、%索引寄存器、比例因子來實現。所以出現了上面代碼的表現形式。

在這個例子中data_items爲起始地址,後面的各項一一對應,這裏的比例因子是4是因爲long類型爲4字節。

 

movl %eax, %ebx 把第一個數載入到%ebx中作爲最大值。

 

後面我進入了循環,我們用start_loop來標記循環的入口(位置)。

start_loop:
cmpl $0, %eax
je loop_exit
incl %edi
movl data_items( , %edi, 4 ), %eax
cmpl %ebx, %eax
jle start_loop
movl %eax, %ebx
jmp start_loop

一個循環第一考慮的問題就是,循環結束的條件,不然寫出死循環就麻煩了。

cmpl —— compare long,比較long類型的大小,結果會記錄在%eflags(狀態寄存器)中

je = jump equal 如果值相等,就跳轉。

cmpl $0, %eax
je loop_exit

表示%eax的值爲0就跳轉到loop_exit的位置,執行這個位置後面的操作。如果不相等就不跳轉,而是繼續執行後面緊更的操作。

 

incl %edi
movl data_items( , %edi, 4 ), %eax

incl —— increase long,所以 incl %edi 是讓%edi的值加1,類似於C語言的 i++ 的效果

所以這兩句很在一起的效果就是索引數據,要檢測的數着存放在%eax中。

 

cmpl %ebx, %eax
jle start_loop
movl %eax, %ebx
jmp start_loop

jle —— jump less equal如果小於等於,跳轉

jmp —— 無條件跳轉

所以這裏就是,如果%eax裏的大值比%ebx中的目前最大值小或相等(注意:比較的方式,到底是那個比那個小),這跳轉到start_loop位置,執行這個位置後面的代碼,也就是跳過後面操作,回到循環的開頭。如果不成立,執行下面步驟,就是把%eax裏面的值載入到%ebx作爲新的最大值。跳會循環開始處。

 

movl $1, %eax
int $0x80

退出代碼就不說了。

對於這個程序,這麼解釋,實在是太累了,最爲教程的前幾期,會講的詳細,每一步都講,到後面基本之講重點。

 

最後,最好在回顧一遍,在寫一遍,你可以對其進行改進,這一次寫,可不是對着代碼敲下來,而是自己寫。

 

附加內容:

數據類型

  • .byte —— 字節類型,只佔用一個字節
  • .int —— 整型,佔用2個字節
  • .long —— 長整型,佔用4個字節
  • .ascii —— ascii碼類型字符,一個字符佔1個字節

大小判斷

  • je = jump equal 如果值相等,就跳轉。
  • jg = jump greater 如果第二個值大於第一個值,跳轉
  • jge = jump greater equal 如果第二個值大於等於第一個值,跳轉
  • jl = jump less equal如果第二個值小於第一個值,跳轉
  • jle = jump less equal如果第二個值小於等於第一個值,跳轉
  • jmp  無條件跳轉

 

注意:這裏的等於只是方便大家理解命令便於理解記憶。

版權聲明

Moriarty_221爲本文的CSDN博客

如未註明,均爲原創,轉載請註明出處

轉載請註明:coskimo » Linux彙編教程03:大小比較操作

版權所有 © 科斯基摩 | 本網站採用cc by-nc-sa 3.0協議進行授權

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章