1. 程式人生 > >轉intel彙編和AT&T彙編的區別

轉intel彙編和AT&T彙編的區別

因為在linux的核心中,很多跟底層硬體接觸的都使用匯編語言,但是Linux不僅使用一種組合語言,除了Intel的組合語言之外,還是用AT&T的組合語言,因此可以說這兩個是一個基礎,Intel的彙編相信很多學計算機的人都學習過,但是AT&T的就不一定了,個人認為他們的思想都是一樣的,只不過是語法不同,初級學習可以看如下的文章(文章轉自http://blog.chinaunix.net/u1/59572/showart_1148334.html)

一、AT&T 格式Linux 彙編語法格式
  
  在 AT&T 彙編格式中,暫存器名要加上 '%' 作為字首;而在 Intel 彙編格式中,暫存器名不需要加字首。例如:
  AT&T 格式
   Intel 格式
  
  pushl %eax
   push eax
  
  
  在 AT&T 彙編格式中,用 '$' 字首表示一個立即運算元;而在 Intel 彙編格式中,立即數的表示不用帶任何字首。例如:
  AT&T 格式
   Intel 格式
  
  pushl $1
   push 1
  
  
  AT&T 和 Intel 格式中的源運算元和目標運算元的位置正好相反。在 Intel 彙編格式中,目標運算元在源運算元的左邊;而在 AT&T 彙編格式中,目標運算元在源運算元的右邊。例如:
  AT&T 格式
   Intel 格式
  
  addl $1, %eax
   add eax, 1
  
  
  在 AT&T 彙編格式中,運算元的字長由操作符的最後一個字母決定,字尾'b'、'w'、'l'分別表示運算元為位元組(byte,8 位元)、字(word,16 位元)和長字(long,32位元);而在 Intel 彙編格式中,運算元的字長是用 "byte ptr" 和 "word ptr" 等字首來表示的。例如:
  AT&T 格式
   Intel 格式
  
  movb val, %al
   mov al, byte ptr val
  
  
  在 AT&T 彙編格式中,絕對轉移和呼叫指令(jump/call)的運算元前要加上'*'作為字首,而在 Intel 格式中則不需要。
  遠端轉移指令和遠端子呼叫指令的操作碼,在 AT&T 彙編格式中為 "ljump" 和 "lcall",而在 Intel 彙編格式中則為 "jmp far" 和 "call far",即:
  AT&T 格式
   Intel 格式
  
  ljump $section, $offset
   jmp far section:offset
  
  lcall $section, $offset
   call far section:offset
  
  
  與之相應的遠端返回指令則為:
  AT&T 格式
   Intel 格式
  
  lret $stack_adjust
   ret far stack_adjust
  
  
  在 AT&T 彙編格式中,記憶體運算元的定址方式是
  section:disp(base, index, scale)
  
  
  而在 Intel 彙編格式中,記憶體運算元的定址方式為:
  section:[base + index*scale + disp]
  
  
  由於 Linux 工作在保護模式下,用的是 32 位線性地址,所以在計算地址時不用考慮段基址和偏移量,而是採用如下的地址計算方法:
  disp + base + index * scale
  
  
  下面是一些記憶體運算元的例子:
  AT&T 格式
   Intel 格式
  
  movl -4(%ebp), %eax
   mov eax, [ebp - 4]
  
  movl array(, %eax, 4), %eax
   mov eax, [eax*4 + array]
  
  movw array(%ebx, %eax, 4), %cx
   mov cx, [ebx + 4*eax + array]
  
  movb $4, %fs:(%eax)
   mov fs:eax, 4
  
  
  二、Hello World!
  
  既然所有程式設計語言的第一個例子都是在螢幕上列印一個字串 "Hello World!",那我們也以這種方式來開始介紹 Linux 下的組合語言程式設計。
  
  在 Linux 作業系統中,你有很多辦法可以實現在螢幕上顯示一個字串,但最簡潔的方式是使用 Linux 核心提供的系統呼叫。使用這種方法最大的好處是可以直接和作業系統的核心進行通訊,不需要連結諸如 libc 這樣的函式庫,也不需要使用 ELF 直譯器,因而程式碼尺寸小且執行速度快。
  
  Linux 是一個執行在保護模式下的 32 位作業系統,採用 flat memory 模式,目前最常用到的是 ELF 格式的二進位制程式碼。一個 ELF 格式的可執行程式通常劃分為如下幾個部分:.text、.data 和 .bss,其中 .text 是隻讀的程式碼區,.data 是可讀可寫的資料區,而 .bss 則是可讀可寫且沒有初始化的資料區。程式碼區和資料區在 ELF 中統稱為 section,根據實際需要你可以使用其它標準的 section,也可以新增自定義 section,但一個 ELF 可執行程式至少應該有一個 .text 部分。下面給出我們的第一個彙編程式,用的是 AT&T 組合語言格式:
  
  例1. AT&T 格式
  
  #hello.s
  
  .data # 資料段宣告
  
   msg : .string "Hello, world!//n" # 要輸出的字串
  
   len = . - msg # 字串長度
  
  .text # 程式碼段宣告
  
  .global _start # 指定入口函式
  
  _start: # 在螢幕上顯示一個字串
  
   movl $len, %edx # 引數三:字串長度
  
   movl $msg, %ecx # 引數二:要顯示的字串
  
   movl $1, %ebx # 引數一:檔案描述符(stdout)
  
   movl $4, %eax # 系統呼叫號(sys_write)
  
   int $0x80 # 呼叫核心功能
  
   # 退出程式
  
   movl $0,%ebx # 引數一:退出程式碼
  
   movl $1,%eax # 系統呼叫號(sys_exit)
  
   int $0x80 # 呼叫核心功能
  
  
  初次接觸到 AT&T 格式的彙編程式碼時,很多程式設計師都認為太晦澀難懂了,沒有關係,在 Linux 平臺上你同樣可以使用 Intel 格式來編寫彙編程式:
  
  例2. Intel 格式
  
  ; hello.asm
  
  section .data ; 資料段宣告
  
   msg db "Hello, world!", 0xA ; 要輸出的字串
  
   len equ $ - msg ; 字串長度
  
  section .text ; 程式碼段宣告
  
  global _start ; 指定入口函式
  
  _start: ; 在螢幕上顯示一個字串
  
   mov edx, len ; 引數三:字串長度
  
   mov ecx, msg ; 引數二:要顯示的字串
  
   mov ebx, 1 ; 引數一:檔案描述符(stdout)
  
   mov eax, 4 ; 系統呼叫號(sys_write)
  
   int 0x80 ; 呼叫核心功能
  
   ; 退出程式
  
   mov ebx, 0 ; 引數一:退出程式碼
  
   mov eax, 1 ; 系統呼叫號(sys_exit)
  
   int 0x80 ; 呼叫核心功能
  
  
  上面兩個彙編程式採用的語法雖然完全不同,但功能卻都是呼叫 Linux 核心提供的 sys_write 來顯示一個字串,然後再呼叫 sys_exit 退出程式。在 Linux 核心原始檔 include/asm-i386/unistd.h 中,可以找到所有系統呼叫的定義。
  
  三、Linux 彙編工具
  
  
  
  Linux 平臺下的彙編工具雖然種類很多,但同 DOS/Windows 一樣,最基本的仍然是彙編器、聯結器和偵錯程式。
  
  
  1.彙編器
  
  彙編器(assembler)的作用是將用匯編語言編寫的源程式轉換成二進位制形式的目的碼。Linux 平臺的標準彙編器是 GAS,它是 GCC 所依賴的後臺彙編工具,通常包含在 binutils 軟體包中。GAS 使用標準的 AT&T 彙編語法,可以用來彙編用 AT&T 格式編寫的程式:
  
  
  [

[email protected] code]$ as -o hello.o hello.s
  
  
  
  
  Linux 平臺上另一個經常用到的彙編器是 NASM,它提供了很好的巨集指令功能,並能夠支援相當多的目的碼格式,包括 bin、a.out、coff、elf、rdf 等。NASM 採用的是人工編寫的語法分析器,因而執行速度要比 GAS 快很多,更重要的是它使用的是 Intel 彙編語法,可以用來編譯用 Intel 語法格式編寫的彙編程式:
  
  
  [[email protected] code]$ nasm -f elf hello.asm
  
  
  
  
  2.連結器
  
  由彙編器產生的目的碼是不能直接在計算機上執行的,它必須經過連結器的處理才能生成可執行程式碼。連結器通常用來將多個目的碼連線成一個可執行程式碼,這樣可以先將整個程式分成幾個模組來單獨開發,然後才將它們組合(連結)成一個應用程式。 Linux 使用 ld 作為標準的連結程式,它同樣也包含在 binutils 軟體包中。彙編程式在成功通過 GAS 或 NASM 的編譯並生成目的碼後,就可以使用 ld 將其連結成可執行程式了:
  
  
  [
[email protected]
code]$ ld -s -o hello hello.o
  
  
  
  
  3.偵錯程式
  
  有人說程式不是編出來而是調出來的,足見除錯在軟體開發中的重要作用,在用匯編語言編寫程式時尤其如此。Linux 下除錯彙編程式碼既可以用 GDB、DDD 這類通用的偵錯程式,也可以使用專門用來除錯彙編程式碼的 ALD(Assembly Language Debugger)。
  
  
  從除錯的角度來看,使用 GAS 的好處是可以在生成的目的碼中包含符號表(symbol table),這樣就可以使用 GDB 和 DDD 來進行原始碼級的除錯了。要在生成的可執行程式中包含符號表,可以採用下面的方式進行編譯和連結:
  
  
  [
[email protected]
code]$ as --gstabs -o hello.o hello.s
  
  
  [[email protected] code]$ ld -o hello hello.o
  
  
  
  
  執行 as 命令時帶上引數 --gstabs 可以告訴彙編器在生成的目的碼中加上符號表,同時需要注意的是,在用 ld 命令進行連結時不要加上 -s 引數,否則目的碼中的

相關推薦

intel彙編AT&T彙編區別

因為在linux的核心中,很多跟底層硬體接觸的都使用匯編語言,但是Linux不僅使用一種組合語言,除了Intel的組合語言之外,還是用AT&T的組合語言,因此可以說這兩個是一個基礎,Intel的彙編相信很多學計算機的人都學習過,但是AT&T的就不一定了,個人認

Linux下gdb顯示intelat&t彙編

在windows下使用習慣了intel彙編,在Linux下看的難受,在gdb下使用 set disassembly-flavor intel  轉換為intel格式的彙編 set disassembly-flavor att 轉換為att格式的彙編

關於AT&T彙編c語言的相互呼叫的分析

這方面很多人寫了blog,這次我也是學習,從objdump等工具分析。 ------------------------c中調用匯編------------------------------- 首先給出c檔案 #include<stdio.h> int m

經常聽說AT&T彙編Intel彙編,還能聽到ARM彙編,這個ARM彙編與前兩個有什麼關聯?

origin: https://zhidao.baidu.com/question/424592744355848412.htmlAT&T彙編和Intel彙編,是兩種不同組合語言格式,與具體CPU關係不大,只是

AT&T彙編心得之間接定址LEA指令

AT&T彙編心得(1)定址方式:0x4(%esp)的操作是把暫存器esp中的值取出,然後加上4,得到的值作為地址,間接定址得到需要的資料例如:pushl -0x4(%ecx)該指令的含義是取出暫存器ecx的值,減去4,將得到的值作為地址,在記憶體找到該地址對應的值,將

關於AT&T 彙編:64 位與32 位的區別

下面列出一些不同之處,可以參考這個文件,將會有更詳細的資訊(System V Application Binary Interface AMD64 Architecture Processor Supplement)。 1. 64位系統中函式呼叫不再採用單純壓棧的方式:下

GUN ARM彙編中標號的引用在彙編C語言中區別(monitor_flash_len = _bss_start

u-boot/cpu/xx/start.S中: _TEXT_BASE:  .word TEXT_BASE /*uboot映像在SDRAM中的重定位地址,我設定為0xa170 0000 */  .globl _armboot_start  _armboot_start:  .w

AT&T 彙編移位運算

 1.移位乘法       sal destination       sal %c1, destination       sal shifter, destination       第一種格式destination的值向左移1位,這等同於使值乘以2.  線第二種

linux-AT&T彙編,把32位暫存器的值以16進位制字串打印出來

將暫存器的值以16進位制顯示,程式如下:.section .bbs .lcomm buf,10 #定義一個10位元組長度的記憶體區,用來儲存計算出來的字元 .section .text .globl _start _start: //初始化暫存器 movl $0x01abc

Linux 下 AT&T彙編

注:以下內容為學習筆記,多數是從書本、資料中得來,只為加深印象,及日後參考。然而本人表達能力較差,寫的不好。因非翻譯、非轉載,只好選原創,但多數乃摘抄,實為慚愧。但若能幫助一二訪客,幸甚! 大約一年前第三次嘗試自己寫一個玩具作業系統核心玩,寒假時寫到記憶體分頁,沒有搞定,

使用GDB 除錯AT&T 彙編

注:以下內容為學習筆記,多數是從書本、資料中得來,只為加深印象,及日後參考。然而本人表達能力較差,寫的不好。因非翻譯、非轉載,只好選原創,但多數乃摘抄,實為慚愧。但若能幫助一二訪客,幸甚! 除錯在程式設計中是不可缺少的,嘗試使用GDB 除錯一下昨晚的AT&T彙編程

AT&T彙編學習總結二-組合語言程式範例

第四章組合語言範例 建立簡單程式 CPUID指令:CPUID指令是一條彙編指令,不容易從高階語言應用程式執行它。它是請求處理器的特定資訊並且把資訊返回到特定暫存器中的低階指令。 CPUID指令使用

AT&T彙編格式

絕大多數 Linux 程式設計師以前只接觸過DOS/Windows 下的組合語言,這些彙編程式碼都是 Intel 風格的。但在 Unix 和 Linux 系統中,更多采用的還是 AT&

java泛型中<?><T>區別

類型 父類 定義 ext 方法 oid tor 接收 通配符 public static void printColl(ArrayList<?> al){ Iterator<?> it = al.iterator();

:MySQLOracle的一些區別

interval art 年月日 tool 數學運算 ont 簡單 序列號 最大的 有很多應用項目, 剛起步的時候用MYSQL數據庫基本上能實現各種功能需求,隨著應用用戶的增多,數據量的增加,MYSQL漸漸地出現不堪重負的情況:連接很慢甚至宕機,於是就有把數據從MYSQL遷

:HTMLWeb窗體的區別

ont .net 加載 平臺 最快 font -s ext 加載速度 總結:Html就是靜態頁面,可以用來寫錯誤界面等不需要和後臺交互的,簡單的界面;web窗體用來和服務器交互,實現動態的,比較復雜的功能。 一、Html和web窗體的區別: 1、 HTML頁

Java中 ? extends T ? super T區別

前言:向上轉型是安全的,向下轉型是不安全的,除非你知道List中的真實型別,否則向下轉型就會報錯。 extends List<? extends Number> foo3意味著下面的賦值語句都是合法的: List<? extends Number> foo

】SOA微服務的區別

目錄   1、什麼是SOA   2. 什麼是微服務 3. 微服務由來 4. 為什麼需要微服務? 4.1 最期的單體架構帶來的問題 4.2 微服務與單體架構區別 4.3 微服務與SOA區別 5. 微服務本質 6.什麼樣的專案適合微服務 微服務優勢與

? super T? extends T區別應用

經常看見框架很多這樣的泛型寫法<? extends T>,後來終於看了相關資料才明白。 <? extends T>是指“上界萬用字元”,<? super T>是指下界萬用字元。 比較有趣,而且有點燒腦,歸根結底,還是一個上下轉型的問題。 舉例:有3個類

泛型中? super T? extends T區別

原文連結          李璟([email protected]) 經常發現有List<? super T>、Set<? extends T>的宣告,是什麼意思呢?<? super T>表示包括T在內的任何T的父類,<? extends