Linux 彙編語法格式

2021-05-01 21:50:49 字數 4840 閱讀 2921

絕大多數

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

中,可以找到所有系統呼叫的定義。

AT T彙編語法格式

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

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

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

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

絕大多數linux程式設計師以前只接觸過dos windows下的組合語言,這些彙編 都是intel風格的。但在unix和linux系統中,更多採用的還是at t格式,兩者在語法格式上有著很大的不同 在at t彙編格式中,暫存器名要加上 作為字首 而在intel彙編格式中,暫存器名不需要加字首。例如...