AS86 匯編器


內核編程語言和環境

  • 語言編譯過程就是把人類理解的高級語言轉換成計算機硬件能理解和執行的二進制機器指令的過程。這種轉換過程通常會產生一些效率不是很高的代碼。所以一些對運行效率要求高或者性能影響較大的部分代碼就會直接使用匯編語言來編寫。或者對高級語言編譯產生的匯編程序在進行人工修改或優化。

AS86匯編器

  • Linux0.1x系統中使用了兩種匯編器,一種是能產生16位代碼的as86匯編器,使用配套的ld86鏈接器,另一種是GNU的匯編器gas(as),使用GNU ld鏈接器來鏈接產生的目標文件。
  • 可以為80386處理器編制32位代碼,但是linxu系統僅僅使用它們創建16位的啟動引導扇區程序boot/bootsect.s和實模式下初始設置程序boot/setup.s的二進制執行代碼。該編譯器快速小巧,並具有一些GNU gas沒有的特性,例如宏檢查以及更多的錯誤檢測手段,不過該編譯器的語法與GNU as匯編編譯器的語法不兼容。而更接近於微軟的MASM、Borland公司的Turbo ASM和NASM等匯編器的語法,這些匯編器使用了Intel的匯編語言語法,操作數的次序與GNU as的相反。

as86匯編語言語法

  • 匯編器專門用來吧低級匯編語言程序編譯成含機器碼的二進制程序或目標文件。匯編器會把輸入的一個匯編語言程序編譯成目標文件。
  • 匯編的命令行基本格式為:
    • as [選項] -o objfile srcfile
  • 選項用來控制編譯過程以產生指定格式和設置的目標文件。輸入的匯編語言程序srcfile是一個文本文件。該文件內容必須是由換行符結尾的一系列文本行組成。
  • 語句可以是只包含空格、制表符和換行符的空行,也可以是賦值語句、微操作符語句和機器指令語句。賦值語句用於給一個符號或標識符賦值,他由標識符后跟一個等於號,在根一個表達式組成,如“BOOTSEG=0X07C0”,偽操作符語句是匯編器使用的指示符,通常並不產生任何代碼。他由微操作碼和0個或多個操作數組成,每個操作碼都由一個點字符“.”開始,點字符“.”本身是一個特殊的符號,他表示編譯過程中的位置計數器,其值是點符號出現處機器指令第一個字節的地址。
  • 匯編器編譯產生的目標文件objfile通常至少包含三個段或區,即正文段(.text)、數據段(.data)和未初始化數據段(.bss)。
  • 機器指令語句是可執行機器指令的助記符,由操作碼和0個或多個操作數構成。另外任何語句之前都可以有標號,標號是由一個標識符后跟一個冒號“:”組成。在編譯過程中。當匯編器遇到一個標號,那么當前位置計數器的值就會復制給這個標號,因此一條匯編語句通常由標號、指令助記符和操作數三個字段組成,標號位於一條指令的第一個字段。他代表其所在位置的地址,通常指令一個跳轉指令的目標位置,最后還可以跟隨用注釋符。
  • 匯編器編譯產生的目標文件objfile通常包括至少包含三個段或區,即正文段(.text)、數據段(.data)和未初始化數據段(.bss)。正文段是一個已初始化過的段,通常其中包含程序的執行代碼和只讀數據。數據段也是一個已初始化過的段,其中包含可讀、寫的數據,而未初始化的數據段是一個未初始化的段。通常匯編器產生的輸出目標穩健中不會為該段保留空間,但在目標文件鏈接成可執行程序被加載時操作系統會把該段的內容全部初始化為0.匯編語言程序中會產生代碼或數據的語句,都會在這三個中的一個段生成代碼或數據。編譯產生的字節會從“.text”段開始存放,可以使用段控制偽操作符來更改寫入的段。

AS86匯編語言程序

  • 下面是一個簡單的boot.s說明as86匯編程序的結構以及程序中語句的語法,然后給出編譯鏈接和運行方法,最后分別使用as86和ld86的使用方法和編制選項。
!
!boot.S --bootsect.s 的框架程序,用代碼0x07替換串msg1中1字符,然后在屏幕上顯示
!
.globl begtext,begdata,begbss,endtext,enddata,endbss !全局標識符,供ld86鏈接使用。
.text !正文段
begtext:
.data
begdata:
.bss
begbss:
.text
BOOTSEC=0X07C0

entry start
start:
	jmpi go,BOOTSEC !段間跳轉  BOOTSEC 指出跳轉地址 標號go是偏移地址
go:  mov ax,cs
	mov ds,ax
	mov es,ax
	mov [msg1+17],ah !0x07 --->替換字符中一個點符號 喇叭會鳴一聲
	mov cx,#20	!共顯示20個字符
	mov dx,#0x1004	!字符顯示在屏幕第17行、第五列處
	mov bx,#0x000c   !字符顯示屬性  (紅色)
	mov bp,#msg1	!指向要顯示的字符
	mov ax,#0x1301	!寫字符串並移動光標到串結尾處
	int 0x10
loop0: jmp loop0	!死循環
msg1: .ascii "Loading system...!" !調用BIOS中斷顯示的 信息
	  .byte 13,10
.org 510 !表示以后語句從地址510(0x1fe)開始存放
	.word 0xAA55 !有效引導扇區標志,提BIOS加載引導扇區
.text
endtext:
.data
enddata:
.bss
endbss:

  • 上面示例是bootsect.S的一個框架程序,能編譯生成引導扇區代碼。編譯鏈接產生的執行程序可以放入軟盤第一個扇區來引導計算機啟動,啟動后會在屏幕第17行第五列處顯示出紅色字符串“Loading system”,並且光標下移一行。
  • as86匯編程序中,以感嘆號“!”或分號“:”開始的語句其后面為注釋文字。
  • .globl為匯編指示符,以一個字符“.”開始,並不會在編譯時產生任何代碼。匯編指示符由一個偽操作碼,后跟0個或多個操作數組成.
  • BOOTSEG=0x07c0,等號用於定義標識符BOOTSEG所代表的值,因此這個標識符可稱為符號常量。
  • entry為保留關鍵字,用於使ld86在生成的可執行文件中包括進其后指定的標號start,通常在鏈接多個目標文件生成一個可執行文件時應該在其中一個匯編程序中用關鍵字entry指定一個入口標號以便於調試。
  • BLOS將程序加載到物理內存0x7c00,並跳轉到該處時所有寄存器默認為0,此時CS:IP=0X000:0X7c00,這里使用段間跳轉語句就是為了給CS賦值段值0x7c0,該語句執行后CS:IP=0X7C0:0X0005,隨后的兩條語句分別給DS和ES段寄存器賦值,讓他們都指向0x7c0段,這樣便於對程序中的數據進行尋址。
as86 -0 -a -o boots.o boots.s 
ld86 -0 -s -o boot boots.o
dd bs=32 if=boot of=../Linux-0.12-master/Kernel_Image skip=1
  • 第一條命令利用as86匯編器對boot.s程序進行編譯,生成boot.o目標文件。使用鏈接器ld86對目標文件執行鏈接操作,生成MINIX結構的可執行文件boot。-0用於生成8086的16位目標程序,-a用於指定生成與GNU as和ld部分兼容代碼,-s告訴鏈接器去除可執行文件的符號信息。
  • 使用dd刪除boot程序前32B,並將結果寫入Linux-0.12-master/Kernel_Image
qemu-system-x86_64 -m 16 -boot a -fda Linux-0.12-master/Kernel_Image -hda hdc-0.11.img   -s 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM