Linux内核中的汇编语言
阅读数:319 评论数:0
跳转到新版页面分类
Linux
正文
重点:linux内核中的汇编基于AT&T的语法。
一、简介
Linux内核中包含的汇编源码主要由两部分组成:一大部分是内核arch目录和其它目录下的纯汇编文件,以.S为后缀的文件;另一小部分是嵌入在C文件代码中的汇编代码段。
(1)8086汇编(16bit)
(2)x86汇编(32bit)
(3)x64汇编(64bit)
(4)ARM汇编(嵌入式、移动设备)
(1)intel
(2)AT&T
二、Intel 和AT&T
汇编语言源代码主要采用两种语法:AT&T语法和Intel语法,尽管它们都属于第二代语言,但是二者的语法却存在巨大的差异。AT&T汇编语法以%作为所有寄存器名称的前缀,以$作为文字常量(也叫做立即操作数)的前缀。它这样对操作数排序:源操作数位于左边,目的操作数位于右边,使用AT&T语法,GNU汇编器(Gas)和许多其他GNU工具(如gcc和gdb)都使用AT&T语法。
Intel语法与AT&T语法不同,它不需要寄存器和文字前缀,它的操作数排序方式与AT&T语法操作数恰恰相反:源操作数位于右边,目的操作数位于左边,使用Intel语法的汇编器包括微软汇编器(MASM)、Borland的Turbo汇编器(TASM)和Netwide汇编器(NASM)。
intel格式的指令使用大写字母,而AT&T格式的使用小写字母。
intel中基地址使用[],而AT&T使用(),另外处理复杂操作数的语法也不同,intel为segreg:[base+index*scale+disp],而AT&T中为%segreg:disp(base,index,scale)。
AT&T语法中大部分指令操作码的最后一个字母表示操作数大小,b表示byte,w表示word,l表示long。intel中处理内存操作数时也有类似的语法:BYTE PTR, WORD PTR, DWORD PTR
三、指令、伪指令、宏指令
1、指令
每一条指令都对应一种CPU操作。
2、伪指令
伪指令又称伪操作,它是在对源程序汇编期间由汇编程序处理的操作。不生成目标码。
不同的汇编语言伪指令集有所差别。
#define name (参数) \
第1行 \
...
第n-1行 \
第n行
3、宏指令
宏指令是由用户按宏定义格式编写的一段程序,其中语句可以是指令、伪指令和已定义的宏指令。
宏是伪指令,作用是把一个复杂的语句组合用一个简单、易记的形式表示。
.macro 宏名 [参数名列表]
宏体
.endm
四、AT&T语法
#if defined(CONFIG_EVT1)&&!defined(CONFIG_FUSED)
.word 0x2000
.word 0x0
.word 0x0
.word 0x0
#endif
word相当于int类型,是GNU汇编中的元素,word=32bit=4字节
.global就是相当于c语言中的Extern,声明此变量,并且告诉链接器此变量是全局的,外部可以访问。
symbol后面加上一个冒号,表示其是一个标号label,类似c语言goto后面的标号。
标号最多可以包含247个字符,不区分大小写,以字母、数字、下划线、@、$ 、. 等其它符号作为标号的首字母。
标号包含三个属性:类型属性、段属性、偏移属性。类型属性也称为距离属性,分为短标号、远标号和近标号,其分类标准是同不同段、同段距离标号多少;段属性就是段地址,偏移属性代表着标号到首地址的距离,一般以字节为单位。标号可以定义为源文件内局部可见,也可以通过伪指令.globl .global ,有时会和指示符EXPORT 或EXPORT_SYMBOL等,将其声明为全局可见,可在多个文件中使用。
(1)ARM采用RISC架构,CPU本身不能直接读取内存,而需要先将内存中内容加载入CPU中通用寄存器中才能被CPU处理。
(2)ldr(load register)指令将内存内容加载入通用寄存器。
(3)str(store register)指令将寄存器内容加入内存空间中。
LDR{条件} 目的寄存器,<存储器地址>
用于从存储器中将一个32位的字数据传送到目的寄存器中。
MRS{条件} 通用寄存器,程序状态寄存器(CPSR或SPSR)
BIC{条件}{S} 目的寄存器,操作数1,操作数2
用于清除操作数1的某些位,并把结果放置到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
orr{条件}{S} 目的寄存器,操作数1,操作数2
用于两个操作数上进行或运算,并把结果放置到目的寄存器中,操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
msr{条件} 程序寄存器(CPSR或SPSR)_<域>,操作数
msr指令用于将操作数的内容传送到程序状态寄存器的特定域中。其中,操作数可以为通用寄存器或立即数。
.align {alignment} {,fill}{,max}其中:alignment用于指定对齐方式,可能的取值为2的次幂,缺省为4。fill为填充内容,缺省用0填充。max是填充字节数最大值,如果填充字节数超过max,就不进行对齐。
批量数据加载/存储指令
LDM(或STM){条件}{类型} 基址寄存器{!} ,寄存器列表{^}
cmp的功能是相当于减法指令,只是不保存结果,cmp指令执行后,将对标志寄存器产生影响,其他相关指令通过识别这些被影响的标志寄存器来得知比较结果。
表示距离包含它的object的字节偏移。正当情情况下,这个object是SECTIONS,这时它表示的是绝对地址。如果包含它的是SECTIONs内的段,那它表示的就是相对于这个段的相对偏移字节数。
五、其他
是LS语法中的COMMAND,用来指定输入文件的machine arch。
ENTRY也是一个LS的COMMAND,用来设置入口点。如果缺省汇编入口为start标号。
在Arm体系下,一个汇编文件至少有一个ENTRY,在一些体系中,ENTRY表示全局符号的开始,它的结束标志可以END或ENDPROC。END表示数据或者特定函数的结尾,ENDPROC代表普通函数的结尾。
section [address] [(type)] :
[AT(lma)] [ALIGN(section_align)]
[SUBALIGN(subsection_align)]
[constraint]
{
output-section-command
output-section-command
...
} [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp]
其中address为VMA,而AT命令中的为LMA。
指定这个段在编译出来映像文件中的地址(加载地址),如果不使用这个选项,则加载地址等于运行地址。