1. 程式人生 > >ARM裸機全集之ARM體系結構(學習筆記)

ARM裸機全集之ARM體系結構(學習筆記)

ARM體系結構與彙編指令
1.2.1 可程式設計器件的程式設計原理
1.2.1.1 電子器件的發展方向
模擬器件-數字器件
ASIC-可程式設計器件

1.2.1.2.可程式設計期間的特點
CPU在固定頻率的時鐘控制下節奏執行
CPU可以通過匯流排讀取外部儲存裝置中的二進位制指令集,然後解碼執行
這些可以被CPU解碼執行的二進位制指令集是CPU設計的時候確定的,是CPU的設計者(ARM公司)定義的
本質是一串由0和1組成的數字,這就是CPU的彙編指令集


1.2.2 指令集對CPU的意義
1.2.2.1 組合語言與C等高階語言的差別
彙編難寫,C好寫
彙編無可移植性,C語言有一定可移植性,Java等更高階語言移植性更強。
組合語言效率最高,C語言次之,Java等更高階語言效率更低。
彙編不適合完成大型複雜的專案,更高階語言更適合完成更大、更復雜的專案。

1.2.2.2 程式語言的發展過程
純機器碼程式設計
組合語言程式設計
C語言程式設計
C++語言程式設計
Java C#等語言程式設計
指令碼語言程式設計

1.2.2.3 組合語言的本質
彙編的實質是機器指令(機器碼)的助記符
,是一種低階符號語言。
機器指令集是一款CPU的程式設計特徵,是這款CPU的設計者制定的。
CPU的內部電路設計就是為了實現這些指令集的功能。機器指令集就好象CPU的API介面一樣。


總結:

1.可移植性
CPU的機器碼(機器指令集)在CPU的設計階段就已經定死了,不同的CPU擁有不同的機器碼。
而組合語言的本質就是機器碼的助記符,通過彙編器翻譯成機器碼,所以彙編沒有可移植性。
C語言的可移植性是由編譯器決定的,在不同的作業系統上用不同的編譯器,就可以的到相同效果的彙編程式碼。
2.何為高階語言,何為低階語言
語言越高階,越接近人的思維;越低階,越接近機器的思維。
語言越低階,工作效率越高(機器),語言越高階,工作效率越低,但越接近應用層(方便程式設計師使用),
相當於要完成同樣的機器動作,越高階的語言可以使用跟少的程式碼,大大減輕了程式設計師的勞動。


1.2.3 RISC和CISC的區別
1.2.3.1 什麼是RISC、CISC
CISC(300條指令左右,Intel的奔騰)complex instruction computer複雜指令集計算機
最少的指令完成任務,一個功能一個指令,功耗高。
RISC(30條指令,ARM)Reduced Instruction-Set computer 精簡指令集計算機最基本的功能指令集,功耗低,讓軟體來完成具體的任務。


1.2.3.2CPU的發展與RISC和CISC的關係
早期簡單CPU,指令和功能都很有限
CISC年代 —— CPU功能擴充套件依賴於指令集的擴充套件,實質是CPU內部組合邏輯電路的擴充套件。
RISC年代 —— CPU僅提供基礎功能指令(譬如記憶體與暫存器通訊指令,基本運算與判斷指令等),功能擴充套件由使用CPU的人利用基礎架構來靈活實現。
總結:
RISC和CISC慢慢的趨向大一統.



1.2.4 統一編址&獨立編址&哈佛結構&馮諾依曼結構
1.2.4.1 IO(IO其實是CPU與外設的介面,可以習慣的認為就是外設)
何為內部或外部外設(本質就是有沒有在晶片內部)
IO與記憶體統一編址方式(把外設暫存器當作一個記憶體地址來讀寫,以訪問記憶體的方式訪問外設)

IO與記憶體獨立編址方式(通過CPU專用的指令來訪問外設,這就是CISC為什麼有這麼多的指令了,每多一個外設,就要增加相應的指令。)


1.2.4.2記憶體
ROM(Flash)、RAM
前者用來存放程式,後者用來存放資料
記憶體與CPU的關係
通過匯流排直接連線,能達到訪問的最大效率。

1.2.4.3程式與資料
程式執行時兩大核心元素:程式 + 資料
程式是我們寫好的原始碼經過編譯、彙編之後得到的機器碼,這些機器碼可以拿給CPU去解碼執行,CPU不會也不應該去修改程式,所以程式是隻讀的。
資料是程式執行過程中定義和產生的變數的值,是可以讀寫的,程式執行實際就是為了改變資料的值。

1.2.4.4馮諾依曼結構與哈佛結構
馮諾依曼結構:程式與資料放在同樣的記憶體空間裡,彼此沒有界限,容易產生誤差,例如Intel的CPU就是採用的
馮諾依曼結構,所以它的內部程式是可以修改,計算機病毒就是利用了這一點
哈佛結構:程式與資料放在不同的記憶體塊中,雖然都在記憶體中,但他們的地址範圍都是固定的、彼此分離(ROM/RAM),CPU設計時
規定哪個範圍的記憶體地址中的二進位制碼是可以讀寫,而哪個是隻讀的。譬如大部分的微控制器(MCS51、ARM9等)均採用哈佛結構。



1.2.4.5優劣對比
馮諾依曼結構中程式和資料不區分的放在一起,因此安全和穩定性是個問題,好處是處理起來簡單。
哈佛結構中程式(一般放在ROM、flash中)和資料(一般放在RAM中)獨立分開存放,因此好處是安全和穩定性高,缺點是軟體處理複雜一些(需要統一規劃連結地址等



1.2.5 軟體程式設計控制硬體的關鍵---暫存器
1.2.5.1 什麼是暫存器(他是外設的硬體組成部分,不是軟體)
暫存器屬於CPU外設的硬體組成部分
CPU可以像訪問記憶體一樣訪問暫存器
暫存器是CPU的硬體設計者制定的,目的是留作外設被程式設計控制的“活動開關”
正如彙編指令集是CPU的程式設計介面API一樣,暫存器是外設硬體的軟體程式設計介面API。
使用軟體程式設計控制某一硬體,其實就是程式設計讀寫該硬體的暫存器。

1.2.5.2 暫存器分類
SoC中有2類暫存器:通用暫存器和SFR
通用暫存器(ARM中有37個)是CPU的組成部分,CPU的很多活動都需要通用暫存器的支援和參與。
SFR(special function register,特殊功能暫存器)不在CPU中,而存在於CPU的外設中,
我們通過訪問外設的SFR來程式設計操控這個外設,這就是硬體程式設計控制的方法。

1.2.5.3 怎樣通過暫存器來控制硬體
程式設計操作暫存器類似於訪問記憶體
暫存器中每個bit位都有特定含義,因此程式設計操作時需要位操作。
單個暫存器的位寬一般和CPU的位寬一樣,以實現最佳訪問效率


1.2.6 ARM體系結構總結
ARM是RISC
常用ARM彙編指令只有二三十條
ARM是低功耗CPU
ARM的架構非常適合微控制器、嵌入式,尤其是物聯網領域;而伺服器等高效能領域目前主導還是Intel
ARM採用的是I/O與記憶體統一編址
ARM採用的是哈佛結構

1.2.7 S5PV210的地址對映詳解
1.2.7.1 什麼是地址對映
CPU的設計決定了他的地址匯流排,地址匯流排決定了定址空間,定址空間大小就是理想狀態的記憶體大小

1.2.7.2 專業術語
ROM:read only memory 只讀儲存器
RAM:ramdom access memory 隨機訪問儲存器
IROM:internal rom 內部ROM,指的是整合到SoC內部的ROM
IRAM:internal ram 內部RAM,指的是整合到SoC內部的RAM
DRAM:dynamic ram 動態RAM
SRAM,STATIC RANDOM ACCESS MEMORY  就是靜態隨即儲存器
SROM static read only memory 靜態只讀儲存器
ONENAND/NAND: 集合了NANDFlash和NORFlansh的有點(NOR Flash 和 NAND Flash 是現在市場上兩種主要的非易失快閃記憶體技術。)
SFR:special function register
總結:

會看memorry map ,
S5PV210:(記憶)
0x2000_0000 0x3FFF_FFFF  512MB  DRAM 0
0x4000_0000 0x7FFF_FFFF  1024MB DRAM 1
0xD000_0000 0xD000_FFFF  64KB   IROM



1.2.8 CPU和外部儲存器的介面
1.2.8.1 SoC常用外部儲存器
NorFlash
NandFlash
eMMC/iNand/moviNand
oneNAND
SD卡/TF卡/MMC卡
eSSD
SATA硬碟

1.2.8.2 X210開發板支援的外部儲存器
X210有2個版本,Nand版和iNand版,分別使用Nandflash和iNand為外部儲存器。我們使用的是iNand版本,板載4GB iNand
S5PV210共支援4個SD/MMC通道,其中通道0和2依次用作啟動。X210開發板中SD/MMC0通道用於連線板載MMC,因此外部啟動時只能使用SD/MMC2通道(注意通道3不能啟動)。見《S5PV210_iROM_ApplicationNote_Preliminary_20091126.pdf》中P6

總結:

1、現代SoC支援多種外部儲存器
2、外部儲存器主要用來儲存程式(可執行程式碼),相當於電腦的硬碟。
3、各種不同外部儲存器原理不同,大小、價效比不同,一般產品廠家根據需要選擇適合自己產品的外存使用。
4、外部儲存器和CPU連線一般不是通過地址&資料匯流排直接相連,因為地址空間不夠用。一般都是通過專門的介面來連線的



1.2.9S5PV210的啟動過程詳解
記憶體:
SRAM靜態記憶體特點是容量小、價格高,優點是不需要軟體初始化直接上電就能用
DRAM 動態記憶體特點是容量大、價格低,缺點是上電後不能直接使用,需要軟體初始化才可以使用
微控制器中:記憶體需求量小,而且希望開發簡單,適合全部用SRAM 
嵌入式系統:記憶體需求量大,而且沒有NorFlash等啟動介質
PC機:記憶體需求量大,而且軟體複雜,不在乎DRAM的初始開銷,適合全部用DRAM

外存:
NorFlash:特點是容量小,價格高,優點是可以和CPU直接匯流排式相連,CPU上電後可以直接讀取,所以一般用作啟動介質
NandFlash(跟硬碟一樣):特點是容量大,價格低,缺點是不也不知道我們板子上將來接的是能匯流排式訪問,也就是說不能上電後CPU直接讀取,需要CPU執行一些初始化軟體,然後通過時序介面讀寫。

所以一般PC機都是:很小容量的BIOS(Norflash)+很大容量的硬碟(類似於NandFlash)+大容量的DRAM
一般的微控制器:很小容量的NorFlash + 很小容量的SRAM
嵌入式系統:因為NorFlash很貴,所以現在很多嵌入式系統傾向於不用NorFlash,直接用:外接的大容量Nand + 外接大容量DRAM + SoC內建SRAM


S5PV210的啟動過程: 外接的大容量Nand + 外接大容量DRAM + SoC內建SRAM210,還內建了一塊96KB的SRAM(IRAM),同時還有一塊內建64KB的NorFlash(IROM)

第一步:CPU上電後先從內部IROM中讀取預先設定的程式碼,執行。這一段IROM程式碼做了一些基本初始化(CPU時鐘、看門狗。。)(這一段IROM程式碼是三星出廠前設定的,三星也不知道我們的板子將來接的是什麼DRAM);然後這段程式碼會判斷我們的啟動模式(通過硬體跳線可以更改板子的啟動模式),然後從相應的外部儲存器去讀取第一部分程式碼(BL1,大小為16KB);到內部SRAM
第二步:從IRAM去執行剛上一步讀取來BL1,然後執行。BL1負責初始化NandFlash,然後將BL2讀取到I
RAM(剩餘的80kb),然後執行
第三步:從IRAM執行BL2,BL2初始化DRAM,然後將OS讀取到DRAM中,然後啟動os,啟動過程結束。


1.2.11 如何在開發板上選擇不同的啟式
SoC通過OMpin來識別外部啟動介質

體驗從SD0的eMMC啟動

開發板收到預設就是從eMMC啟動,內部預先燒錄了android。

從SD2啟動
可以使用外接SD卡從SD2通道啟動,但這需要先破壞板載的eMMC中的android映象。破壞方法見九鼎官方的裸機教程文件《x210v3開發板裸機教程.pdf》中2.5.2節(P19)
OMpin設定和SD0啟動一樣

USB除錯模式(101101 1xxxx1)



總結:
撥碼開關設定我們只需動OM5即可,其他幾個根本不需要碰。需要SD啟動時OM5打到GND,需要USB啟動時OM5打到VCC
可以先不銷燬eMMC中的android,而使用USB啟動來做裸機除錯。之後課程中我們會使用USB啟動和SD卡啟動兩種方式共同來完成實驗,讓大家對比學習。

1.2.12 ARM的程式設計模式和7種模式
為什麼要分7種模式

1.2.12.1 ARM的基本設定
ARM 採用的是32位架構.
ARM 約定:(不同的CPU有不同的約定,但Byte :8 bits是統一的)
Byte : 8 bits
Halfword :16 bits (2 byte)
Word : 32 bits (4 byte)


大部分ARM core 提供:
ARM 指令集(32-bit) 
Thumb 指令集(16-bit )
Thumb2指令集(16 & 32bit)
Jazelle cores 支援 Java bytecode

1.2.12.2 ARM處理器工作模式
ARM 有7個基本工作模式:
User : 非特權模式,大部分任務執行在這種模式


FIQ :   當一個高優先順序(fast) 中斷產生時將會進入這種模式
IRQ :   當一個低優先順序(normal) 中斷產生時將會進入這種模式
Supervisor :當復位或軟中斷指令執行時將會進入這種模式
Abort : 當存取異常時將會進入這種模式
Undef : 當執行未定義指令時會進入這種模式


System : 使用和User模式相同暫存器集的特權模式
注意:
除User(使用者模式)是Normal(普通模式)外,其他6種都是Privilege(特權模式)
Privilege中除Sys模式外,其餘5種為異常模式。
各種模式的切換,可以是程式設計師通過程式碼主動切換(通過寫CPSR暫存器);也可以是CPU在某些情況下自動切換。
各種模式下許可權和可以訪問的暫存器不同。

1.2.12.3 CPU為什麼設計這些模式?
CPU是硬體,OS是軟體,軟體的設計要依賴硬體的特性,硬體的設計要考慮軟體需要,便於實現軟體特性。
作業系統有安全級別要求,因此CPU設計多種模式是為了方便作業系統的多種角色安全等級需要。


1.2.13 ARM的37個暫存器詳解
1.2.13.1 ARM暫存器

                                            

這裡看到的就是ARM核心裡面的所有暫存器了,一共有37個。我們前面說過,ARM體系一共有7種模式,其中使用者模式和系統模式擁有物理空間上完全相同的暫存器,而其它5種異常模式都有一些自己獨立的暫存器。
我們看圖中左邊顯示的是當前模式的可見的暫存器,右邊顯示的是其它模式備用的暫存器。其中深藍色的部分為當前模式與使用者模式共用的暫存器,而彩色部分為各個暫存器獨立物理空間的暫存器。
這樣安排的好處是當各種異常發生的時候,每種異常模式都可以儲存一些重要的資料,使異常處理程式完成之後返回異常前的程式時不會破壞原有的暫存器或狀態。
System模式使用user模式暫存器集
總結:
ARM共有37個暫存器,都是32位長度
37個暫存器中30個為“通用”型,1個固定用作PC,一個固定用作CPSR,5個固定用作5種異常模式下的SPSR。


1.2.13.2 CPSR程式狀態暫存器


條件位:
N = Negative result from ALU 
Z = Zero result from ALU
C = ALU operation Carried out
V = ALU operation oVerflowed
Q 位:
僅ARM 5TE/J架構支援
指示飽和狀態
J 位
僅ARM 5TE/J架構支援
J = 1:  處理器處於Jazelle狀態
中斷禁止位:
I  = 1: 禁止  IRQ.
F = 1: 禁止  FIQ.
T Bit:
僅ARM  xT架構支援
T = 0: 處理器處於 ARM 狀態
T = 1: 處理器處於 Thumb 狀態
Mode位:處理器模式位


注意:
CPSR中各個bit位表明了CPU的某些狀態資訊,這些資訊非常重要,和後面學到的彙編指令息息相關(譬如BLE指令中的E就和CPSR中的Z標誌位有關)
CPSR中的I、F位和開中斷、關中斷有關
CPSR中的mode位(bit4~bit0共5位)決定了CPU的工作模式,在uboot程式碼中會使用匯編進行設定。


1.2.13.3 PC(r15)程式控制暫存器
PC(Program control register)為程式指標,PC指向哪裡,CPU就會執行哪條指令(所以程式跳轉時就是把目標地址程式碼放到PC中)
整個CPU中只有一個PC(CPSR也只有一個,但SPSR有5個)。



1.2.14 ARM的異常處理方式簡單介紹


1.2.14.1 什麼是異常 
正常工作之外的流程都叫異常
異常會打斷正在執行的工作,並且一般我們希望異常處理完成後繼續回來執行原來的工作
中斷是異常的一種


1.2.14.2 什麼是異常向量表
所有的CPU都有異常向量表,這是CPU設計時就設定好的,是硬體決定的。
當異常發生時,CPU會自動動作(PC跳轉到異常向量處處理異常,有時伴有一些輔助動作)
異常向量表是硬體向軟體提供的處理異常的支援。


1.2.14.3異常的處理機制
當異常產生時, ARM core:
拷貝 CPSR 到 SPSR_<mode>(儲存了Tbit的值,用於異常處理結束返回時,回到這個處理器狀態)
設定適當的 CPSR 位: 
改變處理器狀態進入 ARM 態
改變處理器模式進入相應的異常模式
設定中斷禁止位禁止相應中斷 (如果需要)
儲存返回地址到 LR_<mode>
設定 PC 為相應的異常向量

返回時, 異常處理需要:
從 SPSR_<mode>恢復CPSR
從LR_<mode>恢復PC 
Note:這些操作只能在 ARM 態執行.


總結:
異常處理中有一些是硬體自動做的,有一些是程式設計師需要自己做的。需要搞清楚哪些是需要自己做的,才知道如何寫程式碼。
以上說的是CPU設計時提供的異常向量表,一般成為一級向量表。有些CPU為了支援多箇中斷,還會提供二級中斷向量表,處理思路類似於這裡說的一級中斷向量表。














相關推薦

ARM裸機全集ARM體系結構(學習筆記)

ARM體系結構與彙編指令 1.2.1 可程式設計器件的程式設計原理 1.2.1.1 電子器件的發展方向模擬器件-數字器件ASIC-可程式設計器件 1.2.1.2.可程式設計期間的特點CPU在固定頻率的

arm體系結構學習筆記 part1--處理器模式與暫存器

先來看看arm920t的處理器的七種模式: ARM920T supports seven modes of operation: · User (usr): The normal ARM program execution state · FIQ (fiq): Design

Oracle體系結構學習筆記

Oracle體系結構由例項和一組資料檔案組成,例項由SGA記憶體區,SGA意思是共享記憶體區,由share pool(共享池)、data buffer(資料緩衝區)、log buffer(日誌緩衝區)組成 SGA記憶體區的share pool是解析SQL並儲存執行計劃的,然後SQL根據執行計劃獲取資料時先

Jmeter初級學習Jmeter體系結構

jmeter基本原理 建立一個多執行緒,多執行緒執行取樣器產生大量負載,在執行過程中通過斷言來驗證結果的正確性,通過監聽器來記錄測試結果。若取樣器有引數化的需求,可以通過配置元件或前置處理器來完成;若有關聯需求,可以通過後置處理器來完成。 jmeter執行原理

Spring原始碼學習BeanFactory體系結構

public interface AutowireCapableBeanFactory extends BeanFactory { /** * Constant that indicates no externally defined autowiring. Note that

ARM裸機程式儲存管理器控制SDRAM

本文講的是s3c2440A晶片的儲存管理器,配套的開發板是友善之臂mini2440,首先貼出程式碼 head.s的程式碼: .equ MEM_CTL_BASE, 0x48000000 @定義13個暫存器的首地址 .equ SDRAM_BASE

數據結構學習筆記線性表

所有 圖片 指定 表頭 rem 過程 序列 位置 png 一、概念 什麽是線性表呢? 一個簡單的理解如下: 線性表是由稱為元素(Element)的數據項組成的一種有限且有序的序列 其中,這裏有一個需要註意的地方: 有序是指線性表中的每個元素都有自己的位置,而不是指線

資料結構學習筆記線性表

一、概念 什麼是線性表呢? 一個簡單的理解如下: 線性表是由稱為元素(Element)的資料項組成的一種有限且有序的序列 其中,這裡有一個需要注意的地方: 有序是指線性表中的每個元素都有自己的位置,而不是指線性表中的元素按某種順序排列 二、抽象資料型別定義 要給資料結構定

資料結構學習筆記列表

#include <iostream> using namespace std; typedef int Rank; #define Posi(T) ListNode<T>* //列表節點位置 //節點叫法:頭 首 末 尾 template<ty

資料結構學習筆記棧(含數制轉換,括號匹配,表示式求值轉逆波蘭)

#include <iostream> #include <cstring> #include <ctype.h> #include <string> #include <cstring> #include <

JavaFX入門(二)JavaFX體系結構

本章提供了JavaFX體系結構和生態系統的高階描述。 圖2-1說明了JavaFX平臺的架構元件。圖中的部分描述了每個元件以及這些部件如何互連。JavaFX公共API下面是執行JavaFX程式碼的引擎。它由包含JavaFX高效能圖形引擎的子元件組成,稱為Prism; 一個

資料結構學習筆記——線性表順序表(c語言實現)

1.概念 順序表即線性表的順序儲存結構 ,指的是用一段地址連續的儲存單元依次儲存線性表資料元素。線上性表中,每個資料元素的型別都相同,一般可以用一維陣列來實現順序儲存結構。 2.實現 (1)建立順序表的結構 利用c語言結構體來建立順序表的結構,順序表結構體中

資料結構學習筆記——堆疊鏈式儲存結構(c語言實現)

棧的鏈式儲存結構使用單鏈表實現,同線性表一樣,鏈式儲存結構的堆疊在儲存空間的利用上顯得更加靈活,只要硬體允許一般不會出現溢位的情況。但鏈式棧相對於順序棧稍顯麻煩,若所需堆疊空間確定,順序棧顯得方便一些。關於鏈式和順序式的選擇視具體情況而定。 1.棧的鏈式儲存結構

ARM裸機程式開發——ARM執行模式及暫存器

現在來總結一下ARM的執行模式以及暫存器 ★ARM的執行模式型別 ARM微處理器有7中執行模式:使用者模式(user)、系統模式(system)、一般中斷模式(IRQ)、快速中斷模式(FIQ)、管理模

資料結構學習筆記(四) 圖鄰接表實現深度優先遍歷

一下是使用鄰接表儲存表示,實現圖的深度優先遍歷的示例。 用於遍歷的有向圖如下: #include<iostream> #define MaxVertexNum 6 using namespace std; //抽象資料型別 typedef c

資料結構學習筆記——二叉樹已知兩序排列還原二叉樹

對於非線性資料結構二叉樹,通過人為規定的三種遍歷順序將其轉化為線性結構存入計算機中。 三種遍歷順序即是三種轉換方式: 先序:先訪問當前節點,再訪問左子樹,後訪問右子樹。 中序:先訪問左子樹,再訪問當前節點,後訪問右子樹。 後序:先訪問左子樹,再訪問右子樹,後訪問當前節

金融結算系統的基礎業務賬戶體系結構分析

金融系統的基礎是結算,結算的核心是賬戶,賬戶體系是最基礎的也是最重要的部分,而眾多的業務也都是圍繞賬戶展開的,要了解現在眾多的金融系統(包括網際網路金融)就繞不開賬戶體系。一、先看一下結算系統的幾個抽象

數據結構學習筆記(二) 線性表的順序存儲和鏈式存儲

出錯 初始化 node != test span 輸入 des val 線性表:由同類型數據元素構成有序序列的線性結構  --》表中元素的個數稱為線性表的長度  --》沒有元素時,成為空表  --》表起始位置稱表頭,表結束位置稱表尾 順序存儲:    1 package

Nginx模塊Nginx-Ts-Module學習筆記(一)搶險體驗

學習筆記 體驗 nginx模塊 int images clas tps gin issues 1、通過HTTP接收MPEG-TS2、生產和管理Live HLS 3、按照官方的編譯和配置,當然了我是第一次編譯沒有通過,在作者重新調整下,編譯成功,感謝:@arut https:

數據結構學習筆記-排序/隊/棧/鏈/堆/查找樹/紅黑樹

算法 數據結構排序:插入排序:每次從剩余數據中選取一個最小的,插入已經排序完成的序列中合並排序:將數據分成左右兩組分別排序,然後合並,對每組數據的排序遞歸處理。冒泡排序:重復交換兩個相鄰元素,從a[1]開始向a[0]方向冒泡,然後a[2]...當a[i]無法繼續往前擠的時候說明前面的更小了,而且越往前越小(擠