我們在上一講中,簡單了解了匯程式設計序大概的樣子。接下來我們來了解一下,匯程式設計序的大小比較操作。所以我們以編寫尋找一堆數中的最大值作為學習的載體。
在編寫程式之前,先要分析我們的目的,在得出解決方案。
目的:在一堆數中找到最大的數
思路:要實現這個目的,首先,我們一定要對資料進行索引,每一次比較,兩個數應該分別占用乙個暫存器,得到最大值,所以,我們有乙個暫存器一定是存放最大值的。一開始沒有最大值,我們不妨設第乙個數為最大值,後面一次索引大小比較。得出最大值。索引中還會用到迴圈結構。
在**之前,先說一下用到的暫存器
%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
把上面的**儲存為maximum.s,在編譯鏈結,執行。正常情況下最大應該是97。
現在來具體解釋**:
.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
對於這個程式,這麼解釋,實在是太累了,最為教程的前幾期,會講的詳細,每一步都講,到後面基本之講重點。
最後,最好在回顧一遍,在寫一遍,你可以對其進行改進,這一次寫,可不是對著**敲下來,而是自己寫。
Linux彙編教程03 大小比較操作
我們在上一講中,簡單了解了匯程式設計序大概的樣子。接下來我們來了解一下,匯程式設計序的大小比較操作。所以我們以編寫尋找一堆數中的最大值作為學習的載體。在編寫程式之前,先要分析我們的目的,在得出解決方案。目的 在一堆數中找到最大的數 思路 要實現這個目的,首先,我們一定要對資料進行索引,每一次比較,兩...
Linux彙編教程04 定址方式
這一節,我們主要來討論定址方式,這一點十分重要。我們上一節有稍微提了一下,記憶體位址引用的通用格式 位址或偏移 基址暫存器,索引暫存器,比例因子 結果位址 位址或偏移 基址暫存器 比例因子 索引暫存器 位址或偏移和比例因子必須是常數,剩下的那兩個必須是暫存器,在預設的情況下,都用0來代替。立即定址方...
Linux彙編教程01 基本知識
在我們開始學習linux彙編之前,需要簡單的了解一下計算機的體系結構。我們不需要特別深入的了解,理解了一些基本概念對與我們理解程式會很有幫助。現在計算機的結構體系都是採用馮諾依曼體系結構的基礎上發展過來的。而馮諾依曼的體系有兩個主要組成部分 cpu和記憶體。而我們的組合語言和這兩個部分十分密切。記憶...