印度語口譯證照※ [本文轉錄自 C_and_CPP 看板 #1Cis6A7c ] 作者: purpose (purpose) 看板: C_and_CPP 標題: Re: [問題] C/C++ 中的 asm 該若何學起? 時間: Tue Oct 12 03:12:07 2010 發篇筆記 1、[簡介] 機械說話與80x86 2、[觀念] 組合說話—Intel Style 與 AT&T Style、MASM 與 NASM 3、[教學] 簡單貫穿連接範例—NASM 組合語言 與 C/C++ (Windows 平台) ------------------------------------------------------------- 一、[簡介] 機械語言與80x86 大師家裡用的計較機械叫做小我電腦 (PC)翻譯 可以拿來安裝 Windows、Linux,甚至 Mac OS X...等功課系統。 小我電腦的 CPU 演化歷史,可以說就是 Intel 的歷史。從最早的16位元CPU: 「8088/8086 -> 80286」,再演變到32位元的 80386、80486... 後來因為商標不克不及用數字註冊,Intel 不利用 80586 命名,從586最先, 改名為歷史上的 Pentium CPU。 AMD 也差不多是在 Pentium 時代開始漸漸成為 Intel 在小我電腦處置器上的 競爭者。 可以想見 Intel 就是小我電腦處置器的「唯一制訂者」,Intel自己做新的 CPU 也要向後相容以前的東西,就像 Windows 7 也得要能執行 Windows XP 的程式一般。 翻譯公司在 286 寫的程式,拿去給 486 的 CPU 也要能跑翻譯 所以「個人電腦 CPU = x86 家族」...好啦,可能有人不認同這句話。 你跟美國人講話就要講英文、跟法國人講法文; 跟 x86 家族的處置器講話,就要講「x86 機械說話」; 跟 Intel 8051 單晶片處置器溝通,就講「8051 機械說話」; 在算盤本裡面介紹的處置懲罰器是「MIPS」家族,就用「MIPS 機器說話」跟其溝通。 所有處置懲罰器裡面,x86家族功能當然是最強,每一代都有增添新功能,又要向後相容, 所以其實該說話最複雜、不劃定規矩、欠好學。但只用些根基的功能的話,照舊過得去的翻譯 2、[觀念] 組合語言—Intel Style 與 AT&T Style、MASM 與 NASM 機器說話因為電路關係,原始形式就是 010101 這種二進位形式,但你喜好也能夠 轉成十六進位寫出來給他人看。 下面這是一個 x86 機械說話指令 (instruction): 05 0A 00 00 00 (十六進位暗示) 用人類說法就是你告知某顆 x86 家族的 CPU: 「把翻譯公司的 eax 暫存器內容取出,將其跟10相加,再把結果寫回 eax 暫存器」 用C說話表示法就是: 「eax += 10;」 機械說話情勢明顯太麻煩了。 於是發現了「助憶符號」,好比用 add 代表「相加這個運算動作」; 減法動作,用符號 sub 符號; 將資料從A處複製過去B處的動作,就用 mov 助憶符號標識表記標幟翻譯 add翻譯社 sub, mov...等是運算子,而 eax 暫存器跟 10 是運算介入單元 (運算元)翻譯 若是綜合以上講的運算子跟運算元,想要寫出完全指令時,還會有一個問題! 若有 eax, ecx 兩個運算元,想要把 eax 的值掏出,複製到 ecx 去 到底該寫 mov eax, ecx 照樣 mov ecx翻譯社 eax ? 哪邊濫觞?哪邊目標? AT&T、Intel 各自有一套語法老例。 詳細資料參考這裡: http://www.ibm.com/developerworks/library/l-gas-nasm.html C語言 Intel AT&T 指派運算子的 靠最左側的運算元 靠最右側的運算元 左邊是目標地 是目標地。 是運算成效放置處。 int eax = 4; mov eax, 4 movl $4, %eax (暫存器名稱前,需加 % 符號; 並且4這個立即數值前,需加 $ 符號; 且用 movl 默示 move long 這麼長) 西瓜靠大邊,跟人人一起用 Intel 慣例的寫法就好翻譯 像上面 mov eax翻譯社 4 如許子的指令情勢,都叫「組合說話」,說穿了只是把當初 的「x86 機械說話」寫成比力輕易看懂的形式而已翻譯 既然如許,那 x86 機械語言就一套,助憶符號跟暫存器也固定那幾個。 為什麼最後卻搞出 MASM、TASM、NASM、FASM...這麼多種組合語言呢? MASM,軟體界霸主微軟奉行的組合說話 (固然微軟比來變心去搞 MSIL 的樣子?) NASM,在台灣是僅次於微軟的選擇方案,並且跨多個功課系統平台。文件完整、 有中文書籍在講它,並且狀態不變翻譯 ※ FASM,較新,雷同於NASM,傳聞比力快? ※ TASM,老牌子,目下當今很少人用了,可是有 Turbo Debugger 很壯大,可以 對 16 位元履行檔做偵錯,偶然也值得一用翻譯 上面提到的組合說話都是 Intel Style,而 AT&T 會看到的地方,就是利用「gcc -S」 功能時會出現。可是可以用 objdump 去看 Intel Style 的組語。 假如是 gdb 偵錯則直接就有選項 disassembly-flavor intel 可以切換到 Intel 風格組語翻譯 別離用 VC 跟 GCC ,一樣寫個 C 說話動態函式庫,把某個函數輸出, 天成翻譯公司用 VC 時,可以在函數前面加上 __declspec(dllexport) 告知 VC 將該函數輸出翻譯 也可以寫個「模組界說檔」(*.def) 去記錄哪些函數要輸出。 但是這兩個方法都是 VC 特有,不是 C 說話劃定的翻譯 同樣狀況在組合語言亦同,MASM 也有一些組譯器指令是其專有,而 NASM 沒有翻譯 乃至在語法上,二者也有差異。 詳細資料:http://www.nasm.us/doc/nasmdoc2.html#section-2.2 NASM 對於「LABEL 符號」是有分巨細寫的,MASM 沒有分。 (這不包括暫存器名稱,沒必要非寫 eax 而不寫 EAX, 也不包含 NASM 的假指令,好比 SECTION 巨細寫都可以翻譯) 而且 MASM 有些遭詬病的語法規範,NASM 有對其改良之翻譯 對於 MASM 「某符號」要拿來「當做記憶體位址」用時,需加上 offset 修飾。 對於 NASM 覺得微軟如許太麻煩,直接寫就必然是當位址用,不用加 offset翻譯 MASM 的毛病是 若是寫組譯器指令以下,去界說兩個符號: (MASM、NASM 都支援這兩個假指令) foo equ 1 bar dw 2 equ 指令很近似 #define pi 3.141421356 (...偷用他人的梗) dw 這個假指令,是告知組譯器把此刻這個處所,所對應的記憶體位址, 取別號叫 bar,而且寫入 double-word (4位元組) 到此處, 寄存值為 0x 00 00 00 02。 此時,假如 MASM 有兩個指令如下: mov eax, foo ; foo 因為是 equ 設定出來的值,所以 eax 會獲得 1 mov eax, bar ; bar 因為是「組合說話變數」,故 eax 獲得值是 2 上面兩個指令,語法格局看起來完全一致, 但假如沒去旁觀 foo 跟 eax 的假指令界說,就不克不及剖斷機械碼該翻成哪一個。 假如是用 NASM,因為他強迫劃定只要是「間接取值」者,一概需加上中括號 []翻譯 這個間接取值,意思是第一次取到的值,不是我要的,第二次取到的值才是我要的。 可以想成「間接取值 = 二次取值」。 換言之 mov eax, foo mov eax翻譯社 bar 對於 NASM 來講,不需要去看假指令定義, 因為 bar 跟 foo 都沒有用中括號,所以兩個都做一次取值就好。 亦即 mov eax, bar 會獲得 bar 對應的記憶體位址,而不是 bar 的寄存內容 2。 可是 MASM 很沒規律,因為 foo 是 equ 所定義,所以 eax 得到 1 (沒間接取值); 因為 bar 是一個 dw 界說的「組合說話變數」,所以將會做「間接取值」,先取得 bar 所對應的記憶體位址後,再到該位址再取一次值。 抓4位元組得到 2 來傳給 eax。 3、[教授教養] 簡單連結範例—NASM 組合說話 與 C/C++ (Windows 平台) 存成檔案 xx.c --------------------------------------- #include <stdio.h> int plusTen(int val); int plusEleven(int x) { return x+11; } int main() { printf("return = %d ", plusEleven(1)); printf("return = %d ", plusTen(0x00123456)); return 0; } --------------------------------------- 用 VC 編譯器的話,履行指令 cl /c xx.c 可以獲得對應的目的檔「xx.obj」 從 Visual Studio 200X 號令提醒字元,去下這個 cl 指令,以省略環境變數的設定 存成檔案 fun.asm --------------------------------------- section .text global _plusTen _plusTen: push ebp ;函數初始化工作 mov ebp, esp ;函數初始化工作 mov eax翻譯社 0 mov ax, word [ebp+8] add eax, 10 pop ebp ;函數結尾工作 ret ;返回呼喚函數 (caller),eax 是寄存返回值用 --------------------------------------- 去下載 NASM http://www.nasm.us/pub/nasm/releasebuilds/2.09.02/win32/nasm-2.09.02-win32.zip 解壓縮後,執行指令 nasm -f win32 D:\Desktop\fun.asm 就能取得一樣是 COFF 花樣的目標檔 fun.obj。 簡單來講就是這個目標檔跟 cl /c 獲得的目標檔有一樣花式翻譯 最後再去「Visual Studio 200X 敕令提醒字元」下指令 link xx.obj fun.obj 就可以獲得 xx.exe 完成 C/C++ 跟 NASM 函數的保持了翻譯 ※對道理有愛好可以參考《程式設計師的自天成翻譯公司教養》一書。 section .text 是 NASM 假指令,示意從這行指令以下的內容,翻譯成機械碼後 都要放到 .text 區去。每個 *.obj、*.exe 內部都有 .text 區段。 global 是 NASM 假指令,在這裡示意要把 _function 標籤包孕的機械碼 視為全域函數。 在 C/C++ 你預設寫個函數,像上面的 plusEleven() 就天然會是 這裡說的這類「全域函數」。 利用 dumpbinGUI 對象,跳去 xx.obj、fun.obj 查看符號表,便可 看到 external 字眼。暗示 xx.obj 可以調用 fun.obj 裡面寫 external 的符號,反之則反翻譯 mov ax翻譯社 word [ebp+8] 這個 ebp+8 是代表 plusTen() 函數的「參數1」 查一下 stack frame 的觀念,再用偵錯軟體窺察「函數呼喚」 進入前後的堆疊、暫存器轉變,應當就可以理解。 要申明的是,[ebp+8] 是「二次取值」,當第一次取值獲得 ebp+8 位址假定是 0x0012FF74,接著要在這個處所做二次取值,在 C/C++ 要取幾個位元組的值是看該指標的資料型態。 假如是在 MASM,則是在中括號前寫 word ptr [ebp+8] 代表 2位元組; 若寫 byte ptr [ebp+8] 則代表 1位元組。 而 NASM 跟 MASM 差不多,但必須拿掉 ptr 字眼,不然會組譯毛病。 因C說話還沒公然前,就已留下一堆目標檔、一堆函數,他們都用正常的定名, 一些好記的名字都被用過了,所以 C 說話在使用函數時,其實一概主動加 _ 來定名。 是以本來的 C 函數呼喚固然是 plusTen,但在 fun.asm 裡輸出的全域函數要寫成 _plusTen 才能讓 xx.c 可以貫穿連接到。 ------------------------------------ 關於「目標檔」,參考這篇: http://en.wikipedia.org/wiki/Object_file 都只講微軟平台 在 DOS 時期目標檔名稱也都是 *.obj;履行檔名稱也都是 *.exe, 但這裡的 *.obj 實際上是 OMF 花樣 (Relocatable Object Module Format)。 跟你在 Windows 用 VC 編譯出來的目標檔 *.obj 分歧。 用 nasm -f obj fun.asm 應該就是產生 OMF 花式的目標檔? 用 nasm -f win32 fun.asm 則是產生 COFF 花樣的目的檔。 更正確來講這個 COFF 花式是微軟點竄過的變種 COFF 花樣翻譯 你也能夠叫它 PE/COFF 花式,乃至叫他 PE 花樣也行,要解讀 PE 花樣,其 第一選擇固然也是微軟供應 dumpbin,而軟體 dumpbinGUI 是圖形介面的前端。 真要說的話 dumpbin 也是一個前端,實際上是呼叫 VC 的 link.exe,給潛藏選項 link /DUMP /ALL xx.obj。 http://en.wikipedia.org/wiki/Portable_Executable PE 花式紛歧定是 *.exe 履行檔,也能夠是 *.dll 也能夠是 *.obj...等。 因為 VC 編譯出的目標檔都是 PE 花式,而 VC 的 link.exe 不克不及處理古早的 目標檔 OMF 花式,所以上面需要叫 nasm 用 -f win32 選項去產生 PE 目的檔。 也許會有某個很強的連結器,可以把 OMF 跟 PE 目標檔保持成 PE 執行檔吧? 乃至把 gcc 編出來的目標檔跟 PE 目標檔 link 成 PE 履行檔? 看有沒有人知道囉 ------------------------------------ MASM 組譯器指令清單 http://msdn.microsoft.com/en-us/library/8t163bt0.aspx 恰好看到,彌補上來翻譯 ------------------------------------ (怕以後忘記,再寫篇記錄,上文不改觀,新增內容於下) 16位元記憶體模子—Segment:Offset (分段記憶體模型) 32位元記憶體模型—Flat Memory Model 加 Paging ( http://en.wikipedia.org/wiki/X86_architecture ) 小我電腦 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 釀成 Flat Memory, 邏輯位址就已等於線性位址了。 然後是因為有「分頁機制」武力介入,所以需要先透過度頁機制轉換,線性位址 才會釀成真實的物理位址。 而分頁機制是從 80386 開始使用 (保護模式的完全版也是從 80386 最先)。 那為什麼 16 位元處理器,不使用 Flat Memory Model?為什麼當初的邏輯位址 要先顛末轉換才會釀成線性位址? 因為16位元CPU內部,介入運算的暫存器那時都還逗留在16位元 (如:ax, bx, cx翻譯社 dx),乃至最重要的指令暫存器 (IP) 也是 16 位元, 故只有定位到 0~65535 也就是 64K 記憶體的能力翻譯 Intel 用額外提供的四個「分段暫存器」(CS、DS、ES、SS),搭配其他暫存器後 ,使得每次記憶體定址體例實際上是 Segment:Offset,此時這種位址表達法叫 邏輯位址翻譯 CS 是 Code Segment、DS 是 Data Segment、SS 是 Stack Segment ... 邏輯位址→線性位址,公式是:「Segment Register * 0x10 + Offset」 假設我們有個程式,裡面的「全域變數」(不是放在堆疊的那種區域變數), 有個很大的整數陣列,總共有 128K。當程式執行時,這些資料區段假定放在 「線性位址=物理位址」的 0x0 ~ 0x1FFFF 這段持續的記憶體空間裡。 在邏輯位址(以寫程式的角度去觀看的位址),這 128K 資料會被分成兩段, 第一段是 DS=0 且 offset = 0x0000~0xFFFF,第二段是 DS=1 且 offset = 0x0000~0xFFFF。 換言之,假如我要把某陣列元素移到 ax 暫存器,指令可能長如許 mov ax, word ptr[0x1234] 若是履行這行時 DS=0,則會取到物理記憶體位址 0x01234 處 (第一段); 如果執行這行時 DS=1,則會取道物理記憶體位址 1*0x10 + 0x1234 = 0x11234。 若要讀取最後一個位元組到ax,只要履行以下指令便可: mov ds翻譯社 1 mov al, byte ptr[0xFFFF] 因為不知道當時的 DS 值為多少,所以保險點,先設定 DS,然後因為 ax 是 16 位元,沒必要用到這麼大。所以用 al 寄存即可翻譯 al 就是 ax 暫存器 低 8 位元別名翻譯 (ax 在 32 位元以上的 CPU 時,其實也是 eax 暫存器的低16位元處別號) 當今的執行檔,比如 PE 履行檔,常常內部都有分 .text (.code)、.data, 可能就是承繼當初的記憶體分段機制?

文章來自: https://www.ptt.cc/bbs/ASM/M.1286960542.A.5B9.html有關各國語文翻譯公證的問題歡迎諮詢天成翻譯公司02-77260931

arrow
arrow
    文章標籤
    翻譯社
    全站熱搜
    創作者介紹
    創作者 clarenv6bio 的頭像
    clarenv6bio

    clarenv6bio@outlook.com

    clarenv6bio 發表在 痞客邦 留言(0) 人氣()