as86汇编器
在Linux 0.x系统中使用了两种汇编器(Assembler)。一种是能产生16位代码的as86汇编器,使用配套的ld86链接器;另一种是GNU的汇编器gas(as),使用GNU ld链接器来链接产生的目标文件。这里我们首先说明as86汇编器的使用方法。
as86和ld86是由MINIX-386的主要开发者之一Bruce Evans编写的Intel 8086,80386汇编编译程序和链接程序。在刚开始开发Linux内核时Linus就已经把它移植到了Linux系统上。它虽然可以为80386处理器编制32位代码,但是Linux系统仅用它来创建16位的启动引导扇区程序boot/bootsect.s和实模式下初始设置程序boot/setup.s的二进制执行代码。但是as86的语法与GNU as汇编编译器的语法不兼容,更近似于MASM,NASM等汇编器的语法。这些汇编器都使用了Intel的汇编语言语法。
现代Linux系统上可以直接安装包含as86/ld86的RPM软件包,例如dev86-0.16.3-8.i386.rpm。由于Linux系统仅使用as86和ld86编译和链接上面提到的两个16位汇编程序bootsect.s和setup.s,因此这里仅介绍这两个程序中用到的一些汇编程序语法和汇编命令(汇编提示符)的作用和用途。
as86汇编语言语法
汇编器专门用来把低级汇编语言程序编译成含机器码的二进制程序或目标文件。汇编器会把输入的一个汇编语言程序(例如srcfile)编译成目标文件(objfile)。汇编的命令行基本格式是:
as [选项] -o objfile srcfile
- -0 以16位代码段运行,当使用了高于 8086 指令集的指令时发出警告
- -1 以16位代码段运行,当使用了高于80186指令集的指令时发出警告
- -2 以16位代码段运行,当使用了高于80286指令集的指令时发出警告
- -3 以32位代码段运行,不对任何指令发出警告信息
特殊字符
- ;!注释符
- $ 16进制数的前缀,C风格的前缀,比如0x1234也可使用
- % 2进制数的前缀
- #立即数的前缀
- [ ] 间接寻址运算符
伪指令
.globl
.globl伪操作符用于定义随后的标号是外部的或全局的,并且即时不使用也强制导入。
赋值语句
赋值语句“BOOTSEG=0x07C0”。等号“=”用于定义标识符BOOTSEG所代表的值,因此这个标识符可称为符号常量。这个值与C语言中的写法一样,可以使用十进制,八进制和十六进制。
entry
告知链接程序,程序从start标号处开始执行,也就是start段的地址作为第一条指令所在的地址。entry是保留关键字,用于使链接器ld86在生成的可执行文件中包括进其后指定的标号“start”。
段间跳转
每一个标号都是一个段。jmpi可以实现段间跳转。
标号
标号由一个标识符后跟一个“:”组成。一条汇编语句通常由标号(可选),指令助记符(指令名)和操作数3个字段组成。标号位于一条指令的第一个字段,它代表其所在位置的地址,通常指明一个跳转指令的目标位置。
定位内存的方法(寻址方式)
- 直接寄存器寻址
mov bx,ax
jmp bx !修改IP的值为bx寄存器中的内容
- 间接寄存器寻址
mov [bx],ax
jmp [bx] !将bx中的内容作为偏移地址,段地址默认保存在ds中
- 绝对寻址
mov ax,1234 !将内存地址1234(msgl)中的内容送到ax中
mov ax,msgl
mov ax,[msgl]
- 索引寻址
mov ax,msg[bx] !把第二个操作数所指内存位置的值送入ax中
mov ax,msgl[bx*4+si]
as86汇编语言程序
下面我们以一个简单的框架示例程序boot.s来说明as86汇编程序的结构以及程序中语法的语句,然后给出编译链接和运行方法,最后再分别列出as86和ld86的使用方法和编制选项。
示例程序是一个bootsect.s的一个框架程序,能编译生成引导扇区的代码。其中为了演示说明某些语句的使用方法,故意加入了无意义的第20行语句。
bootsect.s 框架程序
!
!boot.s -- bootsect.s 的框架程序。用0x07替换串msgl中一个字符,然后在屏幕上显示。
!
.globl begtext,begdata,begbss,endtext,enddata,endbss
.text
begtext:
.data
begdata:
.bss
begbss
.text
BOOTSEG = 0x7C00
entry start
start:
jmpi go,BOOTSEG ! jmpi段间跳转指令,跳转到BOOTSEG:go[段地址:偏移地址]
go:
mov ax.cs
mov ds.ax
mov es,ax
mov [msgl+17],ah
mov cx,#20
mov dx,#0x1004
mov bx,#0x000c
mov bp,#msgl
mov ax.#0x1301
int 0x10
loop0:
jmp loop0 ! 段内跳转指令
msgl:
.ascii "Loading system ..."
.byte 13,10
.org 510
.word 0xAA55
.text
endtext:
.data
enddata:
.bss
endbss:
以上内容是《Linux内核完全注释》的学习笔记