Linux彙編教程02:編寫第一個彙編程序

Linux彙編

學習一門語言,最好的方式就是在運用中學習,那麼在這一章節中,我們開始編寫我們的第一個彙編程序。當然作爲第一個程序,其實十分的簡單,但可以給大家一個基本的輪廓,瞭解彙編大概是這樣的。

 

我們這個程序實際上沒什麼作用,只是簡單的推出而已。下面就是程序的範例

 

# 目的: 退出程序並向Linux內核返回一個狀態碼

# 輸入: 無

# 輸出: 返回一個狀態碼。在程序運行結束後可以通過 echo $? 來讀取狀態碼

# 變量: %eax保存系統調用號 %ebx保存返回狀態

 

.section .data

 

.section .text

.globl _start

_start:

movl $1, %eax # 這是退出程序的Linux內核命令號

movl $0, %ebx # 返回的狀態碼

int $0x80 # 喚醒內核以執行退出命令

linux-assembler-tutorial-02-write-the-first-assembler-image00

完成上面的源代碼,進行彙編

32位機器:as exit.s -o exit.o

64位機器:as –32 exit.s -o exit.o

 

在命令中,as是彙編命令,exit.s 是源文件 -o 是重命名,讓我們生成的文件叫exit.o,exit.o就是目標文件。在Linux爲 .o 後綴,在Windows下爲 .obj 後綴。

目標文件是用機器語言寫的代碼,接下來我們需要使用鏈接器進行鏈接。

32位機器:ld exit.o -o exit

64位機器:ld -melf_i386 exit.o -o exitls

 

ld就是鏈接器命令

要運行exit的話,可以使用 ./exit 命令。當你輸入命令,點完回車之後,光標只是進入了下一行,畢竟我們這個程序只是退出而已。

不過但你運行完程序馬上輸入 echo $? 會發現屏幕上會出現一個0。這個0就是返回的狀態碼

linux-assembler-tutorial-02-write-the-first-assembler-image01

接下來我們開始分析每個部分。

以#號開頭的爲註釋

 

.section .data

在彙編中,任何以小數點開始的指令都不會被翻譯爲機器指令,這些針對彙編本身的指令有彙編程序處理,實際上並不會在計算機上運行,這些指令是彙編指令。.section 指令是把程序分成幾個區塊。

.section .data 命令是數據段的開始,數據段中要列出程序數據所需的內存空間。我們這個程序太過簡單,所以沒有數據,這個命令其實也可以不寫。保留這個指令只是爲了保留程序的結構完整,知道程序的基本框架。

 

.section .text 是文本段,也就是代碼區啦,這裏容納程序指令

 

.globl  _start

這一條指令中 _start 是一個符號,幫助人理解而已,在彙編和鏈接過程中會被替換。一般來說,符號用來標記程序或數據的位置,所以通過符號而不是內存中的位置編號來指代他們。

 

.globl 表示彙編程序不應該在彙編之後把這個符號舍棄,因爲連接器還需要它。_start 是一個特殊符號,總是使用 .globl 來標記,應爲這個標記是程序的入口。

 

_start:

定義_start標籤的值。當彙編程序對程序進行彙編的時候,必須爲每一個數值和指令分配地址。標籤告訴彙編程序以符號的值作爲下一條指令或下一個數據元素的位置。這樣,如果數據或指令的實際物理地址更改了,也不需要重新引用,應爲符號會自動獲取新值。

 

下面開始就是真正的計算機指令了。

 

movl $1, %eax

 

當程序運行時該指令將數值1移入%eax寄存器中。 movl 指令有兩個操作數,一個是源操作數,另一個是目的操作數。根據上一講,$1 是立即尋址方式,在指令中就包含需要的數字。這裏1是源操作數,%eax是目的操作數。操作數的類型一般是數字,內存位置引用或寄存器。而 movl 的作用是從內存位置複製一個字大小的數據到另一個位置。(PS:movb的話操作數是字節)。1移入%eax是讓系統調用exit。進行系統調用時,必須把系統調用號加載到%eax中,有些系統調用還需要其他寄存器也包含有值。

 

x86處理器上的通用寄存器

 

  • %eax
  • %ebx
  • %ecx
  • %edx
  • %edi
  • %esi

除了通用寄存器,還有幾個專用寄存器

  • %ebp
  • %esp
  • %eip
  • %eflags

 

引申一點,在x86處理器的通用寄存器都以e開頭,e 是 extern 的意思,即擴展。主要是因爲以前的x86處理器是16位的,後來才變爲32位,爲了向前兼容,保留了舊名,在前面加上了e作爲32位的擴展寄存器。而在64位採用的是r前綴,比如說%rax就是64位的%eax寄存器。大家可以試着把前面的代碼改一下,彙編,鏈接,運行。

 

在進行系統調用的情況下,操作系統還需要將狀態嗎加載到%ebx,這個值後背返回給系統

 

movl $0, %ebx

這句命令和上面類似,就不解釋了。

 

int $0x80

int 表示中斷,0x80是中斷號。還有,0x80是16進制數,不是10進制的80。

 

版權聲明

Moriarty_221爲本文的CSDN博客

如未註明,均爲原創,轉載請註明出處

轉載請註明:coskimo » Linux彙編教程02:編寫第一個彙編程序

版權所有 © 科斯基摩 | 本網站採用cc by-nc-sa 3.0協議進行授權

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章