Linux下AT T彙編語法格式簡介

2021-08-25 17:48:47 字數 3509 閱讀 7675

絕大多數linux程式設計師以前只接觸過dos/windows下的組合語言,這些彙編**都是intel風格的。但在unix和linux系統中,更多採用的還是at&t格式,兩者在語法格式上有著很大的不同:

在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下AT T彙編語法格式簡介

一 at t 格式linux 彙編語法格式 在 at t 彙編格式中,暫存器名要加上 作為字首 而在 intel 彙編格式中,暫存器名不需要加字首。例如 at t格式 intel格式 pushl eax push eax 在 at t 彙編格式中,用 字首表示乙個立即運算元 而在 intel 彙編格...

AT T彙編語法格式

1.暫存器的引用要在暫存器前加 如mov eax,ebx 2.運算元排列是左源右目的,如上例表示把值從eax暫存器mov到ebx暫存器 3.常數 立即數前面要加 如mov 4,ebx 4.對於變數加 表示取位址。如mov value,ebx表示傳值給ebx,而mov value,ebx表示傳位址給e...

AT T下彙編語法

mov long 32bits mov word 16bits mov byte 8bits 取有效位址 偏移量 lea ignore int,edx 表示把ignore int處的有效位址傳給edx note 是去ignore int處的偏移量,而不是ignore int處儲存的內容 使用方法 l...