彙編語言常識

一 數據表示
1
十進制結尾用D或d
二進制結尾用B或b
十六進制結尾用H或h
八進制結尾用Q或q

2 字符的ASCII表示
標準的ASCII字符集分爲4組,每組32個字符。
第一組 0~1FH 是一組不可打印字符,稱爲控制字符
第二組 各種標點符號、專用字符和數字
第三組 26個大寫字母(41H~5AH)及6個專用字符
第四組 26個小寫字母及(61H~7AH)5個專用字符和一個控制符

3 BCD
BCD是一種十進制數的二進制編碼表示,有以下兩種格式:
a 壓縮BCD格式
 用4個二進制位表示一個十進制位
b 非壓縮BCD格式

4 CPU
cpu主要由算術邏輯部件、控制部件和寄存器組成,其任務是執行內存中的指令序列。


5 彙編程序通常以.s作爲文件名後綴
as hello.s -o hello.o
ld hello.o -o hello

6 彙編程序中以.開頭的 名稱並不是指令的助記符,不會被翻譯成機器指令。
.section指示把代碼劃分成若干個段,程序被操作系統加載執行時,每個段被加載到不同的地址,具有不同的讀、寫、執行權限。
.data斷保存程序的數據,是可讀可寫的,C程序的全局變量屬於.data段

符號在彙編中代表一個地址,可以用在指令中。

movl $1,%eax//數據傳送指令,CPU內部產生一個數字1,然後傳送到eax寄存器中。mov的後綴l表示long,說明是32位的傳送指令。

CPU內部產生的數叫做立即數,在彙編程序中,立即數前面要加$,寄存器前面要加%,以便跟符號名區分開。

int $0x80
a int指令稱爲軟中斷指令,可以用這條指令故意產生一個異常,異常的處理和中斷類似,CPU從用戶模式切換到特權模式,然後跳轉到內核代碼中執行異常處理程序。
b int指令中哦姑娘的立即數0x80是一個參數,在異常處理中要根據這個參數決定如何處理。在linux內核中int 0x80這種異常稱爲系統調用。
c eax和ebx寄存器的值是傳遞給系統調用的兩個參數。eax的值是系統調用號,1表示_exit調用,ebx的值則是傳遞給_exit的參數,也就是退出狀態。

7 X86的寄存器
X86的通用寄存器有eax、ebx、ecx、edx、edi、esi。
除法指令要求被除數在eax寄存器中,餘數在edx寄存器中。

X86的特殊寄存器有ebp、esp、eip、efiags。
eip:程序計數器
eflags:保存計算過程中產生的標誌位
進位 CF 溢出 OF 零ZF 負數 SF

ebp和esp用於維護函數調用的堆棧。

data_items:
 .long 3,67,34,222,45,75,54,34,44,33,22,11,66,0
.long指示聲明一組數,每個數佔32位,相當於C中的數組
數組開頭有個標號data_items,彙編器會把數組的首地址作爲data_items符號所代表的地址。

出了.long之外,常用的數據聲明還有:
.byte 聲明一組數,每個數佔8位
.ascii 例如:.ascii "hello word"

edi(目的變址寄存器)寄存器保存數組的當前位置。
ebx 保存到目前爲止找到的最大值。

movl data_items(,%edi,4), %eax
把數組的第0個元素傳送到eax寄存器上。data_items是數組的首地址,edi的值是數組的下標,4表示數組的每個元素佔有4個字節。那麼數組第edi個元素的地址應該是data_items+edi*4。

start_loop表示開始循環,loop_exit表示結束循環。

cmpl $0, %eax
cmpl指令將兩個操作數相減,但計算結果並不保存,只是根據計算結果改變eflags寄存器中的標誌位。如果兩個操作數相等,則計算結果爲0,eflags中的ZF位置1。
je是一個條件跳轉指令,它檢查eflags中的ZF位,ZF位爲1則發生跳轉,ZF位爲0則不跳轉。
比較指令和條件跳轉指令是配合使用的,前者改變標誌位,後者根據標誌位作出判斷。

incl %edi  //將edi 的值加1

cmpl %ebx, %eax
jle start_loop
把當前數組元素eax和目前爲止找到的最大值ebx 做比較,如果前者小於等於後者,則最大值沒有變,跳轉到循環開頭比較下一個數,否則繼續執行下一條指令。jle 也是一個條件跳轉指令,le表示less than or equal。

jmp 是一個無條件跳轉指令,什麼條件也不判斷,直接跳轉。

8 寄存器
1 eax 累加器   2 ebx 基址寄存器  3 ecx 計數寄存器  4 edx 數據寄存器

1~~4 數據寄存器

5 esi 源變址寄存器  6 edi 目的變址寄存器

5~6變地寄存器
1~~6 通用寄存器

7 ebp 基址指針 8 esp 堆棧指針

7~8 指針寄存器
 
9 eflags 標誌寄存器 10 eip 指令指針

9~~10 專用寄存器

11 CS 代碼寄存器 12 ds 數據斷寄存器 13 ss 堆棧寄存器 14 es 附加段寄存器

11~~14 段寄存器

15 fs

16 gs

9 尋址方式
內存尋址在指令中可以表示成如下的通用格式:
ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)
它所表示的地址可以這樣計算出來:
FINAL ADDRESS = ADDRESS_OR_OFFSET + BASE_OR_OFFSET + MULTIPLIER * INDEX

其中ADDRESS_OR_OFFSET和MULTIPLIER必須是常數,BASE_OR_OFFSET和INDEX必須是寄存器

直接尋址:
只使用ADDRESS_OR_OFFSET尋址,例如movl ADDRESS, %eax 把ADDRESS地址處的32位數傳送到eax 寄存器。

變址尋址(Indexed Addressing Mode) 。movl data_items(,%edi,4), %eax 就屬於這種尋址方式,用於訪問數組元素比較方便。

間接尋址(Indirect Addressing Mode)。只使用BASE_OR_OFFSET尋址,例如movl (%eax), %ebx ,把eax 寄存器的值看作地址,把這個地址處的32位數傳送到ebx 寄存器。注意和movl %eax, %ebx 區分開。

基址尋址(Base Pointer Addressing Mode)。只使用ADDRESS_OR_OFFSET和BASE_OR_OFFSET尋址,例如movl 4(%eax), %ebx ,用於訪問結構體成員比較方便,例如一個結構體的基地址保存在eax 寄存器中,其中一個成員在結構體內的偏移量是4字節,要把這個成員讀上來就可以用這條指令。

立即數尋址(Immediate Mode)。就是指令中有一個操作數是立即數,例如movl $12,%eax 中的$12 ,這其實跟尋址沒什麼關係,但也算作一種尋址方式。

寄存器尋址(Register Addressing Mode)。就是指令中有一個操作數是寄存器,例如movl $12, %eax 中的%eax ,這跟內存尋址沒什麼關係,但也算作一種尋址方式。

10 ELF文件
可重定位的目標文件(Relocatable)
可執行文件(Executable)
共享庫(Shared Object)

目標文件:
ELF文件格式提供了兩種不同的視角,在彙編器和鏈接器看來,ELF文件是由Section Header Table描述的一系列Section的集合,而執行一個ELF文件時,在加載器(Loader)看來它是由Program Header Table描述的一系列Segment的集合。

我們在彙編程序中用.section 聲明的Section會成爲目標文件中的Section,此外匯編器還會自動添加一些Section(比如符號表)。

Segment是指在程序運行時加載到內存的具有相同屬性的區域,由一個或多個Section組成,比如有兩個Section都要求加載到內存後可讀可寫,就屬於同一個Segment。

目標文件需要鏈接器做進一步處理,所以一定有Section Header Table;可執行文件需要加載運行,所以一定有Program Header Table;而共享庫既要加載運行,又要在加載時做動態鏈接,所以既有Section Header Table又有Program Header Table。

  們知道,C語言的全局變量如果在代碼中沒有初始化,就會在程序加載時用0初始化。這種數據屬於.bss 段,在加載時它和.data 段一樣都是可讀可寫的數據,但是在ELF文件中.data 段需要佔用一部分空間保存初始值,而.bss 段則不需要。也就是說,.bss 段在文件中只佔一個Section Header而沒有對應的Section,程序加載時.bss 段佔多大內存空間在Section Header中描述。

.rel.text 告訴鏈接器指令中的哪些地方需要重定位

objdump工具可以把程序中的機器指令反彙編

發佈了1 篇原創文章 · 獲贊 2 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章