x86組合語言- 第一章| 組合語言觀念
文章推薦指數: 80 %
西瓜靠大邊,跟大家一起用Intel 慣例的寫法就好。
像上面mov eax, 4 這樣子的指令形式,都叫「組合語言」,說穿了只是把當初的「x86 機器 ...
Thiswebsite
Archives
Categories
Tags
About
Donate
RSS
歡迎!您似乎正在使用廣告攔截器。
請考慮通過禁用您的廣告攔截器來支持我。
J.J.Huang
2019-07-01
x86組合語言
瀏覽次數:次
{{moment(1561942800000).fromNow()}}
x86組合語言-第一章|組合語言觀念
程式、技術越來越多,但是我在學習的過程中,發現會一直回去研究、探討、學習基礎的知識。
因為前面的CE教學,發現組合語言在後面會需要一些基礎,於是乎上網找了些文章,發現很多啊⋯。
下面這些內容是2010年的資料了,我覺得內容不錯還是有參考價值;基本上是部分轉載,只是希望自己有概念,建議閱讀過稍微了解即可。
機器語言與80x86大家家裡用的計算機器叫做個人電腦(PC),可以拿來安裝Windows、Linux,甚至MacOSX…等作業系統。
個人電腦的CPU演變歷史,可以說就是Intel的歷史。
從最早的16位元CPU:「8088/8086->80286」,再演化到32位元的80386、80486…後來因為商標不能用數字註冊,Intel不使用80586命名,從586開始,改名為歷史上的PentiumCPU。
AMD也差不多是在Pentium時代開始慢慢成為Intel在個人電腦處理器上的競爭者。
可以想見Intel就是個人電腦處理器的「唯一制定者」,Intel自己做新的CPU也要向後相容以前的東西,就像Windows7也得要能執行WindowsXP的程式一般。
你在286寫的程式,拿去給486的CPU也要能跑。
所以「個人電腦CPU=x86家族」…好啦,可能有人不認同這句話。
你跟美國人講話就要講英文、跟法國人講法文;跟x86家族的處理器講話,就要講「x86機器語言」;跟Intel8051單晶片處理器溝通,就講「8051機器語言」;在算盤本裡面介紹的處理器是「MIPS」家族,就用「MIPS機器語言」跟其溝通。
所有處理器裡面,x86家族功能當然是最強,每一代都有增加新功能,又要向後相容,所以其實該語言最複雜、不規則、不好學。
但只用些基本的功能的話,還是過得去的。
組合語言—IntelStyle與AT&TStyle、MASM與NASM機器語言因為電路關係,原始形式就是010101這種二進位形式,但你喜歡也可以轉成十六進位寫出來給別人看。
下面這是一個x86機器語言指令(instruction):
1050A000000(十六進位表示)
用人類說法就是你告訴某顆x86家族的CPU:「把你的eax暫存器內容取出,將其跟10相加,再把結果寫回eax暫存器」
用C語言表示法就是:
1eax+=10;
機器語言形式顯然太麻煩了。
助憶符號於是發明了「助憶符號」,比如用add代表「相加這個運算動作」;減法動作,用符號sub標記;將資料從A處複製過去B處的動作,就用mov助憶符號標記。
add,sub,mov…等是運算子,而eax暫存器跟10是運算參與單元(運算元)。
如果綜合以上講的運算子跟運算元,想要寫出完整指令時,還會有一個問題!若有eax,ecx兩個運算元,想要把eax的值取出,複製到ecx去
到底該寫moveax,ecx還是movecx,eax?哪邊來源?哪邊目的?
AT&T、Intel各自有一套語法慣例
C語言
Intel
AT&T
指派運算子的左邊是目的地inteax=4;
靠最左邊的運算元是目的地。
moveax,4
靠最右邊的運算元是運算結果放置處。
movl$4,%eax(暫存器名稱前,需加%符號;而且4這個立即數值前,需加$符號;且用movl表示movelong這麼長)
西瓜靠大邊,跟大家一起用Intel慣例的寫法就好。
像上面moveax,4這樣子的指令形式,都叫「組合語言」,說穿了只是把當初的「x86機器語言」寫成比較容易看懂的形式而已。
記憶體模型如果需要更詳細的了解可以參考x86
16位元記憶體模型—Segment:Offset(分段記憶體模型)
32位元記憶體模型—FlatMemoryModel加Paging
個人電腦x86家族的CPU,在16位元時代是8088/8086/80286這三位;而x86家族第一個32位元始祖是劃時代的80386。
8088跟8086的位址匯流排都有20條線,每條線都是一端連接記憶體,一端連接處理器,在高低電位變化下(0、1),總共可有2^20種控制變化。
換言之,依照每個記憶體位址對應一個位元組的慣例,可以定位2^20大小的記憶體位址;80286則進化到24條位址線,定址能力達2^24,即16M記憶體。
省麻煩,把它當成跟8088/8086一樣,只能定址到1M記憶體就好。
在x86的術語中,記憶體位址可以分成三種:
邏輯位址
線性位址
真實位址(物理位址)
必須先「邏輯位址→線性位址」,然後接著才是「線性位址→真實位址」。
自從32位元CPU出現(自80386後),記憶體Model變成FlatMemory,邏輯位址就已經等於線性位址了。
然後是因為有「分頁機制」武力介入,所以需要先透過分頁機制轉換,線性位址才會變成真正的物理位址。
而分頁機制是從80386開始使用(保護模式的完整版也是從80386開始)。
那為什麼16位元處理器,不使用FlatMemoryModel?為什麼當初的邏輯位址要先經過轉換才會變成線性位址?
因為16位元CPU內部,參與運算的暫存器當時都還停留在16位元(如:AX,BX,CX,DX),甚至最重要的指令暫存器(IP)也是16位元,故只有定位到0~65535也就是64K記憶體的能力。
Intel用額外提供的四個「分段暫存器」(CS、DS、ES、SS),搭配其他暫存器後,使得每次記憶體定址方式其實是Segment:Offset,此時這種位址表達法叫邏輯位址。
CS是CodeSegment、DS是DataSegment、SS是StackSegment…
邏輯位址→線性位址,公式是:「SegmentRegister*0x10+Offset」
假設我們有個程式,裡面的「全域變數」(不是放在堆疊的那種區域變數),有個很大的整數陣列,總共有128K。
當程式執行時,這些資料區段假設放在「線性位址=物理位址」的0x0~0x1FFFF這段連續的記憶體空間裡。
在邏輯位址(以寫程式的角度去觀看的位址),這128K資料會被分成兩段,第一段是DS=0且offset=0x0000~0xFFFF,第二段是DS=1且offset=0x0000~0xFFFF。
換言之,如果我要把某陣列元素移到ax暫存器,指令可能長這樣
1movax,wordptr[0x1234]
如果執行這行時DS=0,則會取到物理記憶體位址0x01234處(第一段);如果執行這行時DS=1,則會取道物理記憶體位址1*0x10+0x1234=0x11234。
若要讀取最後一個位元組到ax,只要執行以下指令即可:
12movds,1moval,byteptr[0xFFFF]
因為不知道當時的DS值為多少,所以保險點,先設定DS,然後因為ax是16位元,不必用到這麼大。
所以用al存放即可。
al就是ax暫存器低8位元別名。
(ax在32位元以上的CPU時,其實也是eax暫存器的低16位元處別名)
現今的執行檔,比如PE執行檔,往往內部都有分.text(.code)、.data,可能就是承襲當初的記憶體分段機制?
註:以上參考了[心得]個人的x86組合語言觀念筆記
CheatEngine-第十章|CETutorialStep9
x86組合語言-第二章|x86架構及暫存器解釋
延伸文章資訊
- 1第7講C語言轉成組合語言 - 國立清華大學開放式課程
推廣初期的重點包括了,邀請傑出教學教師及教學單位參與製作、培養數位內容協製 ... Q1: 如何把C程式碼轉成x86組合語言程式碼? ... Q2: 全域變數轉成組語後的型式.
- 2微算機原理與應用林銘波編著--- 全華科技圖書公司第2章電腦 ...
第2章電腦結構與組合語言. 2.1. 本章目標. • 了解電腦的基本功能與原理. • 了解組譯程式與組合語言程式. • 了解組合語言程式的建立與執行. • 了解基本的組譯程式假指令.
- 3組合語言- 維基百科,自由的百科全書
組合語言使用輔助記憶碼(Mnemonics)來代替和表示特定低階機器語言的操作。特定的組譯目標指令集可能會包括特定的運算元。許多組譯程式可以辨識代表位址和常數的標籤( ...
- 4組合語言(第七版)(國際版) - 博客來
- 5x86組合語言- 第一章| 組合語言觀念
西瓜靠大邊,跟大家一起用Intel 慣例的寫法就好。 像上面mov eax, 4 這樣子的指令形式,都叫「組合語言」,說穿了只是把當初的「x86 機器 ...