绝大多数Linux程序员以前只接触过DOS/Windows下的汇编语言,这些汇编代码都是Intel风格的。但在Unix和Linux系统中,更多采用的还是AT&T格式,两者在语法格式上有着很大的不同:
在AT&T汇编格式中,寄存器名要加上' %'作为前缀;而在Intel汇编格式中,寄存器名不需要加前缀。例如:
AT&T格式
|
Intel格式
|
pushl %eax
|
push eax
|
在AT&T汇编格式中,用'$'前缀表示一个立即操作数;而在Intel汇编格式中,立即数的表示不用带任何前缀。例如:
AT&T格式
|
Intel格式
|
pushl $1
|
push 1
|
AT&T和Intel格式中的源操作数和目标操作数的位置正好相反。在Intel汇编格式中,目标操作数在源操作数的左边;而在AT&T汇编格式中,目标操作数在源操作数的右边。例如:
AT&T格式
|
Intel格式
|
addl $1, %eax
|
add eax, 1
|
在AT&T汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀'b'、'w'、'l'分别表示操作数为字节(byte,8比特)、字(word,16比特)和长字(long,32比特);而在Intel汇编格式中,操作数的字长是用"byte ptr"和"word ptr"等前缀来表示的。例如:
AT&T格式
|
Intel格式
|
movb val, %al
|
mov al, byte ptr val
|
在AT&T汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上'*'作为前缀,而在Intel格式中则不需要。
远程转移指令和远程子调用指令的操作码,在AT&T汇编格式中为"ljump"和"lcall",而在Intel汇编格式中则为"jmp far"和"call far",即:
AT&T格式
|
Intel格式
|
ljump $section, $offset
|
jmp far section:offset
|
lcall $section, $offset
|
call far section:offset
|
与之相应的远程返回指令则为:
AT&T格式
|
Intel格式
|
lret $stack_adjust
|
ret far stack_adjust
|
在AT&T汇编格式中,内存操作数的寻址方式是
section:disp(base, index, scale)
|
而在Intel汇编格式中,内存操作数的寻址方式为:
section:[base + index*scale + disp]
|
由于Linux工作在保护模式下,用的是32位线性地址,所以在计算地址时不用考虑段基址和偏移量,而是采用如下的地址计算方法:
disp + base + index * scale
|
下面是一些内存操作数的例子:
AT&T格式
|
Intel格式
|
movl -4(%ebp), %eax
|
mov eax, [ebp - 4]
|
movl array(, %eax, 4), %eax
|
mov eax, [eax*4 + array]
|
movw array(%ebx, %eax, 4), %cx
|
mov cx, [ebx + 4*eax + array]
|
movb $4, %fs:(%eax)
|
mov fs:eax, 4
|
Hello World!
真不知道打破这个传统会带来什么样的后果,但既然所有程序设计语言的第一个例子都是在屏幕上打印一个字符串"Hello World!",那我们也以这种方式来开始介绍Linux下的汇编语言程序设计。
在Linux操作系统中,你有很多办法可以实现在屏幕上显示一个字符串,但最简洁的方式是使用Linux内核提供的系统调用。使用这种方法最大的好处是可以直接和操作系统的内核进行通讯,不需要链接诸如libc这样的函数库,也不需要使用ELF解释器,因而代码尺寸小且执行速度快。
Linux是一个运行在保护模式下的32位操作系统,采用flat memory模式,目前最常用到的是ELF格式的二进制代码。一个ELF格式的可执行程序通常划分为如下几个部分:.text、.data和.bss,其中.text是只读的代码区,.data是可读可写的数据区,而.bss则是可读可写且没有初始化的数据区。代码区和数据区在ELF中统称为section,根据实际需要你可以使用其它标准的section,也可以添加自定义section,但一个ELF可执行程序至少应该有一个.text部分。下面给出我们的第一个汇编程序,用的是AT&T汇编语言格式:
例1.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#调用内核功能
|
初次接触到AT&T格式的汇编代码时,很多程序员都认为太晦涩难懂了,没有关系,在Linux平台上你同样可以使用Intel格式来编写汇编程序:
例2.Intel格式
; hello.asm
section .data;数据段声明
msg db "Hello, world!", 0xA;要输出的字符串
len equ $ - msg;字串长度
section .text;代码段声明
global _start;指定入口函数
_start:;在屏幕上显示一个字符串
mov edx, len;参数三:字符串长度
mov ecx, msg;参数二:要显示的字符串
mov ebx, 1;参数一:文件描述符(stdout)
mov eax, 4;系统调用号(sys_write)
int 0x80;调用内核功能
;退出程序
mov ebx, 0;参数一:退出代码
mov eax, 1;系统调用号(sys_exit)
int 0x80;调用内核功能
|
上面两个汇编程序采用的语法虽然完全不同,但功能却都是调用Linux内核提供的sys_write来显示一个字符串,然后再调用sys_exit退出程序。在Linux内核源文件include/asm-i386/unistd.h中,可以找到所有系统调用的定义。
分享到:
相关推荐
linux内核编程入门(第一部分)(第一章)at&t汇编语法格式.part3.rar
linux内核编程入门(第一部分)(第一章)at&t汇编语法格式.part1.rar
linux内核编程入门(第一部分)(第一章)at&t汇编语法格式.part2.rar
我当初找的时候也找了很长时间,现在讲的大多都是intel格式的, 这种很少见, 希望对你有帮助
但在 Unix 和 Linux 系统中,更多采用的还是 AT&T 格式,两者在语法格式上有着很大的不同,因此应对AT&T汇编应有一个基本的了解和熟悉。 我们在LINUX下用C编写一段最简单的helloworld程序,命令为hello.c #...
一、简介 二、LINUX汇编语法格式(AT&T与INTEL汇编的区别) 三、简单程序 四、LINUX汇编工具 五、系统调用 六、命令行参数 七、GCC内联汇编 八、小结
汇编语言的优点是速度快,可以直接对硬件进行操作,这对...本文为那些在Linux 平台上编写汇编代码的程序员提供指南,介绍 Linux 汇编语言的语法格式和开发工具,并辅以具体的例子讲述如何开发实用的Linux 汇编程序。
1. AT&T 汇编语言与已经学过的 mips 汇编语言相比,语法格式相近,但具体的指令以及参数有很大 2. AT&T 汇编语言通过与 C 语言内联,能够更加地
早期的linux两个进程AAAAABBBBB!不是AT&T的汇编语法,用Inter汇编语法。里面有编译方法,包括源文件,可执行二进制文件(elf格式),img映像文件。开发环境:LINUX。本程序在BOCH,VirtualPC2007通过
而且 MASM Intel 格式的汇编代码,可比 GCC AT&T 格式的便于阅读多了。 编辑汇编代码,推荐使用 Notepad++,完美支持 MASM 语法高亮。 首先下载我修改好的 VS 版 Linux 0.11 源码,解压后打开解决方案。 右键点击 ...
S2.2 汇编语法(AT&T asm VS Intel asm).............................................18 S2.3 Hello world!示例...............................................................................20 ...
内容简介 本书从只有二十行的引导扇区代码出发,一步一步地向读者呈现一个操作系统框架的完成过程。书中不仅关注代码本身,同时关注完成这些代码的思路和过程。本书不同于其他的理论型书籍,而是提供给读者一个...
内容简介 本书从只有二十行的引导扇区代码出发,一步一步地向读者呈现一个操作系统框架的完成过程。书中不仅关注代码本身,同时关注完成这些代码的思路和过程。本书不同于其他的理论型书籍,而是提供给读者一个...
简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级、中级、高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情、执着,对IT的憧憬、向往...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...