linux源代码中除了bootsect.s和head.s使用Intel汇编语言之外,其他的源代码都是使用AT&T汇编语言。虽然本科期间学习了汇编语言的相关知识,但是还是没有学习过AT&T汇编语言,因此在进行操作系统学习期间查看源代码时,会产生理解上的困难。这里会对AT&T的部分语言进行相应的介绍:
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
entry start
start:
在setup.s源代码的开始部分会出现上面的代码,那么每个表示的是什么意思呢?下面将做一一讲解。
.text:表示该节中包含程序的代码,需指出该节是只读节。
.data:这种节包含程序已初始化的数据,也就是说,包含具有初值的那些变量
.bss:
•这个节包含程序还未初始化的数据,也就是说,包含没有初值的那些变量。当操作系统装入这个程序时将把这些变量都置为0
•使用.bss比使用.data的优势在于,.bss节在编译后不占用磁盘的空间,这样编译、连接生成的代码的尺寸会比较小。
•尽管在磁盘上不占空间,但是在可执行文件被读入内存后系统还是会为.bss节分配内存
.ascii:语法:.ascii “string” ….
•ascii 表示零个或多个(用逗号隔开)字符串,并把每个字符串(结尾不自动加“\0”字符)中的字符放在连续的地址单元。于此类似的 .asciz指令定义的字符串会在结尾处自动加 “\0”字符
.fill:语法:.fill repeat , size , value
•含义是反复拷贝size个字节,重复repeat次 ,其中size和value是可选的,默认值分别为1和0
.globl:语法:.globl symbol
•.globl使得连接程序(ld)能够看到symbol。如果你的局部程序中定义了symbol,那么,与这个局部程序连接的其他局部程序也能存取symbol
.rept endr:语法:.rept count
…….
.endr
•把.rept指令与.endr指令之间的行重复count次
.space:语法:.space size , fill
•这个指令保留size个字节的空间,每个字节的值为fill
.byte/.word/.long:语法:.byte/.word/.long expressions
•预留1个字节/字/双字,并将这个字节的内容赋值为expression,若是用逗号隔开的多个expression,则为预留多个这样的字节/字/双字,并将它们的内容依次赋值。
.set:设定常数,就好像C程序中的#define的作用一样
AT&T汇编格式
#hello.s
.data # 数据段声明
msg : .string "Hello, world!\\n" # 要输出的字符串
len = . - msg # 字串长度
.text # 代码段声明
.global _start # 指定入口函数
_start: # 在屏幕上显示一个字符串
movl $len, %edx # 参数三:字符串长度
movl $msg, %ecx # 参数二:要显示的字符串
movl $1, %ebx # 参数一:文件描述符(stdout)
movl $4, %eax # 系统调用号(sys_write)
int $0x80 # 调用内核功能
# 退出程序
movl $0,%ebx # 参数一:退出代码
movl $1,%eax # 系统调用号(sys_exit)
int $0x80 # 调用内核功能
两个语法之间的区别:
1.寻址方式:Intel的指令格式是segreg:[base+index*scale+disp],而AT&T的格式是%segreg:disp(base,index,scale)。
Intel语法 | AT&T语法 |
[eax] | (%eax) |
[eax + _variable] | _variable(%eax) |
[eax*4 + _array] | _array(,%eax,4) |
[ebx + eax*8 + _array] | _array(%ebx,%eax,8) |
2.标识长度的操作码前缀:在AT&T汇编中远程跳转指令和子过程调用指令的操作码使用前缀“l”,分别为ljmp,lcall,与之相应的返回指令伪lret。例如:
Intel语法 | AT&T语法 |
CALL SECTION:OFFSET | lcall $secion:$offset |
JMP FAR SECTION:OFFSET | ljmp $secion:$offset |
RET FAR STACK_ADJUST | lret $stack_adjust |
3.标识长度的操作码后缀:在AT&T的操作码后面有时还会有一个后缀,其含义就是指出操作码的大小。“l”表示长整数(32位),“w”表示字(16位),“b”表示字节(8位)。而在Intel的语法中,则要在内存单元操作数的前面加上byte ptr、 word ptr,和dword ptr,“dword”对应“long”。
Intel语法 | AT&T语法 |
Mov al,bl | movb %bl,%al |
Mov ax,bx | movw %bx,%ax |
Mov eax,ebx | movl %ebx,%eax |
Mov eax, dword ptr [ebx] | movl (%ebx),%eax |