歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

Linux下的匯編程序設計

作者:周天陽    引言:     匯編語言是低級語言,與硬件和操作系統緊密聯系。個人電腦以前都是用DOS,現在發展成了Windows 98,而另一個操作系統Linux也正在崛起。下面比較一下這三個操作系統:         操 作 系 統   優 點   缺 點   價 格     DOS   較穩定,速度快   無法充分發揮計算機性能,沒有圖形界面   較低     WINDOWS 98   操作簡便,     應用軟件多,硬件兼容性好   不穩定,經常死機,速度慢   高     Linux   性能優秀,非常穩定,界面美觀,操作簡便   缺乏軟件廠商支持,應用軟件少   免費       表 一 操作系統比較         由以上的比較可知,Linux操作系統本身具有較大優勢,它的普及應該只是時間問題,所以如何在Linux下開發軟件是我們計算機系學生必須學習與研究的一個課題。     Linux下的主要編程語言是C,同時Linux還支持其他許多編程語言,匯編語言作為最重要的編程語言之一,當然也包括在內。它能夠完成許多其他語言所不能完成的功能。要學習Linux編程,就必須要學習Linux下的匯編程序設計。下面我就來介紹一下Linux下的匯編程序設計。         Linux匯編簡介:     一、匯編語言的優缺點:     由於Linux是用C寫的,所以C自然而然的就成為了Linux的標准編程語言。大部分人都把匯編給忽略了,甚至在因特網上找資料都是非常的困難,很多問題都需要靠自己來嘗試。我認為這樣對待匯編語言是不公平的,不能只看到它的缺點,當然也不能只看到它的優點,下面把它的優缺點作一個比較:     優點:匯編語言可以表達非常底層的東西     l 可以直接存取寄存器和I/O     l 編寫的代碼可以非常精確的被執行     l 可以編寫出比一般編譯系統高效的代碼     l 可以作為不同語言或不同標准的接口     缺點:匯編語言是一個非常低級的語言     l 非常冗長單調,在DOS下編程時就可以體會到     l 易出BUG,且調試困難     l 代碼不易維護     l 兼容性不好,與硬件關系非常緊密     總的來說,匯編語言要用在必須的地方,盡量少用匯編編寫大型程序,多采用inline模式。     二、匯編語言工具:     DOS下常用的工具MASM和TASM到Linux下就用不起來了,Linux有自己的匯編工具,而且種類非常的多。其中Gas可以算是標准配置,每一種Linux中都包括有Gas,但是GAS采用的不是我們通常在DOS下采用的匯編語法,它采用的是AT&T的語法格式,與intel語法格式有很大的不同。     如果要采用與DOS接近的語法格式,就必須用另一種匯編工具NASM,NASM基本與MASM相同,但也有不少地方有較大區別,特別涉及到操作系統原理時,與DOS可以說是截然不同。         Linux匯編程序設計:     一、Hello,world!     幾乎所有的語言入門篇都是以“Hello,world!”為例,那麼我也以Hello,world!為例開始。         ;-------------NASM’s standalone Hello-World.asm for Linux --------   section .text   extern puts   global main     main:   push dWord msg ;stash the location of msg on the stack.   call puts ;call the "puts" routine (libc?)   add esp, byte 4 ;clean the stack?   ret ;exit.     msg:   db "Hello World!",0     編譯:   nasm –f elf hello.asm   gcc –o hello hello.o     說明:這個程序實際上是調用了,Linux系統的puts函數,原理與調用DOS下C語言的函數相同,先用Extern聲明puts是外部函數,再把參數(即msg的地址)壓入堆棧,最後Call函數實現輸出。   我們再來看一個程序:         section .text   global main     main:   mov eax,4 ;4號調用   mov ebx,1 ;ebx送1表示stdout   mov ecx,msg ;字符串的首地址送入ecx   mov edx,14 ;字符串的長度送入edx   int 80h ;輸出字串   mov eax,1 ;1號調用   int 80h ;結束   msg:   db "Hello World!",0ah,0dh   (編譯同上一個程序)     這個程序與DOS程序十分相似,它用的是linux中的80h中斷,相當於DOS下的21h中斷,只是因為Linux是32位操作系統,所以采用了EAX、EBX等寄存器。但是Linux作為一個多用戶的操作系統與DOS又是有著非常大的區別的。要寫出有特色的程序,不了解操作系統和硬件是不行的。下面我介紹一下Linux操作系統。         二、Linux操作系統簡介:     操作系統實際是抽象資源操作到具體硬件操作細節之間的接口。對Linux這樣的多用戶操作系統來說,它需要避免用戶對硬件的直接訪問,並防止用戶之間的互相干擾。所以Linux接管了BIOS調用和端口輸入輸出,關於端口輸入輸出方面請參閱Linux IO-Port-Programming HOWTO。而要通過Linux對硬件硬件進行訪問就需要用到System Call,實際上是許多C的函數,可以在匯編程序中調用,調用方法與DOS下的匯編完全相同,而且用ASM匯編時不用鏈接額外的庫函數。     Linux與DOS的主要區別在於內存管理、進程(DOS下無進程概念)、文件系統,其中內存管理和進程與匯編編程的關系比較密切:     1、內存管理:     對任一台計算機而言,其內存以及其他資源都是有限的。為了讓有限的物理內存滿足應用程序對內存的大需求量,Linux采用了稱為“虛擬內存”的內存管理方式。Linux將內存劃分為容易處理的“內存頁”,在系統運行過程中,應用程序對內存的需求大於物理內存時,Linux可將暫時不用的內存頁交換到硬盤上,這樣,空閒的內存頁可以滿足應用程序的內存需求,而應用程序卻不會注意到內存交換的發生。     2、進程     進程實際是某特定應用程序的一個運行實體。在Linux系統中,能夠同時運行多個進程,Linux通過在短的時間間隔內輪流運行這些進程而實現“多任務”。這一短的時間間隔稱為“時間片”,讓進程輪流運行的方法稱為“調度”,完成調度的程序稱為調度程序。通過多任務機制,每個迸程可認為只有自己獨占計算機,從而簡化程序的編寫,每個進程有自己單獨的地址空間,並且只能由這一進程訪問,這樣,操作系統避免了進程之間的互相干擾以及“壞”程序對系統可能造成的危害。     為了完成某特定任務,有時需要綜合兩個程序的功能,例如一個程序輸出文本,而另一個程序對文本進行排序。為此,操作系統還提供進程間的通訊機制來幫助完成這樣的任務。Linux中常見的進程間通訊機制有信號、管道、共享內存、信號量和套接字等。     三、Linux下的匯編工具:     Linux下的匯編工具可謂百家爭鳴,不像DOS下都要給MASM和TASM給控制了。但是Linux下每一種匯編工具都有很大的區別,要想全部掌握幾乎是不可能的,下面我介紹幾種常用的匯編工具,重點介紹NASM及其使用和語法。     1、GCC     GCC其實是GNU的C語言產品,但它支持Inline Assemble,在GCC中inline assemble使用就像宏一樣,但它比宏能更清楚更准確的表達機器的工作狀態。     C是匯編編程的一個高度概括,它可以減少許多匯編中的麻煩,特別是在GCC這個C編譯器中,assemble似乎起不了多大的作用。     2、GAS     GAS是Linux各版本中基本的匯編工具,但它采用的是AT&T的語法標准與Intel的語法標准有很大的不同,對於DOS編程的我們來說,學習起來是非常困難的。當然如果要精通Linux下的匯編編程,學習GAS也是非常必要的,具體的語法標准可以參看Using GNU Assembler。     3、GASP     GASP是GAS的擴展,它增強了GAS對宏的支持。     4、NASM     NASM是linux中語法與DOS最為相像的一種匯編工具。雖說如此,它與MASM也是有著很大區別的。     l NASM的使用格式如下:     Nasm –f -o     例如:     Nasm -f elf hello.asm     將把hello.asm匯編成ELF object文件,而     Nasm -f bin hello.asm -o hello.com     會把hello.asm匯編成二進制可執行文件hello.com     Nasm –h     將會列出NASM命令行的完整說明。     NASM不會有任何輸出,除非有錯誤發生。     -f 在Linux下主要有aout和ELF兩種,如果你不確定你的Linux系統應該用AOUT還是ELF,可以在NASM目錄中輸入 File nasm ,如果輸出nasm: ELF 32-bit LSB executable i386 (386 and up) Version 1表示是ELF,如果輸出nasm: Linux/i386 demand-paged executable (QMAGIC)表示是aout。         l NASM與MASM的主要不同:     首先與linux系統一樣,nasm是區分大小寫的,Hello與hello將是不同的標識符,如果要匯編到DOS或OS/2,需要加入UPPERCASE參數。     其次,nasm中內存操作數都是以[ ]表示。     在MASM中     foo equ 1   bar dw 2   mov ax,foo   mov ax,bar   將被匯編成完全不同的指令,雖然它們在MASM中的表達方式完全一樣。而NASM完全避免了這種混亂,它使用的是這樣的規則:所有對內存的操作都必須通過[ ]來實現。例如上例中對bar的操作就要寫成如下形式 mov ax,[bar]。由此可見,nasm中對offset的使用也是沒有必要的(nasm中無offset)。Nasm對[ ]的使用與masm也有所不同,所有的表達式都必須寫在[ ]中,下面舉兩個例子來說明:     Masm Nasm   Mov ax,table[di]   Mov ax,[table+di]     Mov ax,es:[di]   Mov ax,[es:di]     Mov ax,[di]+1   Mov ax,[di+1]       Nasm 中不存儲變量類型,原因很簡單masm中通過[ ]尋址方式的變量也必須要指定類型。Nasm中不支持LODS, MOVS, STOS, SCAS, CMPS, INS, OUTS,只支持lodsb、lodsw等已經指定類型的操作。Nasm中不再有assume操作,段地址完全取決於存入段寄存器的值。     關於NASM的使用方法及語法還可以參閱NASM使用手冊。         結論:     我認為不論是在Windows/DOS下還是在Linux下完完全全用匯編編一個大型程序已經是不可能了,也不會有人願意去這樣做。在windows下我們可以用VC,在Linux/Xwindows下我們可以用C甚至C++ Builder,但是像VC、C++ Builder之類的工具盡量隱藏了底層的調用,同時也阻隔了成為高手的機會,因為編出來的程序無法了解它的執行過程也就使編程中最重要的“可預測”性變得很低。正因為如此匯編才有它存在的必要性,同時還有一個更重要的原因,正如《超級解霸》的作者梁肇新所說:“編程序的重點不是“編”,而是調試程序,理論上的完美在實現的時候會遇到很多細節問題,這些問題必須調試才能解決。我的編程習慣是一天寫五天調試,《超級解霸》是調試出來的,而不是寫出來的。調試就涉及到匯編的問題,不進行匯編級的調試是不徹底的,也不能讓人放心。         參考資料:     l Jan’s Assemble Homepage     by Jan Wagemakers 8.1999     l Linux Assemble HOWTO     by Konstantin Boldyshev and Fran鏾is-Ren?Rideau 12.1999     l Linux/i386 System Calls     By Konstantin Boldyshev 1999    

 




Copyright © Linux教程網 All Rights Reserved