汇编在LINUX系统下的意义远远大于WINDOWS系统,LINUX内核部分代码就是汇编编写的。然后,绝大多数 Linux 程序员以前只接触过DOS/Windows 下的汇编语言,这些汇编代码都是 Intel 风格的。但在 Unix 和 Linux 系统中,更多采用的还是 AT&T 格式,两者在语法格式上有着很大的不同,因此应对AT&T汇编应有一个基本的了解和熟悉。
我们在LINUX下用C编写一段最简单的helloworld程序,命令为hello.c
#include <stdio.h>
int main()
{
printf("hello,world\n");
exit(0);
}
然后,使用GCC编译,同时使用-s参数生成中间汇编代码,看看AT&T汇编的真实面目
gcc -S hello.c
.file "hello.c"
.section .rodata
.LC0:
.string "hello,world"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
movl $.LC0, (%esp)
call puts
movl $0, (%esp)
call exit
.size main, .-main
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits
汇编器(assembler)的作用是将用汇编语言编写的源程序转换成二进制形式的目标代码。Linux 平台的标准汇编器是 GAS,它是 GCC 所依赖的后台汇编工具,通常包含在 binutils 软件包中。
AT&T汇编主要有以下特点:
1、在 AT&T 汇编格式中,寄存器名要加上 '%' 作为前缀。
如:
把eax寄存器的内容复制到ebx中
movl %eax,%ebx
2、用 '$' 前缀表示一个立即操作数。
如:将1复制到eax中
movl $1, %eax
3、目标操作数在源操作数的右边
movl %eax,%ebx
eax是源操作数,ebx是目标操作数
4、在 AT&T 汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀'b'、'w'、'l'分别表示操作数为字节(byte,8 比特)、字(word,16 比特)和长字(long,32比特)
比如:
movl对32位进行操作,将eax寄存器32位的内容复制到ebx中
movl %eax, %ebx
movw对16位进行操作,将ax寄存器的内容复制到bx中
movw %ax, %bx
movb对8位进行操作,将al寄存器的内容复制到bl中
movb %al, %bl
我们再以入栈为例:
pushl %ecx # 32位ecx的内容入栈
pushw %cx # 16位ecx的内容入栈
pushl $180 # 80做为一个32位整数入栈
pushl data # data变量内容入栈,长度为32位
pushl $data # 这一个操作很特别,在变量前面加上$表示取变量的地址,这是将data变量的地址入栈
5、在 AT&T 汇编格式中,绝对转移和调用指(jump/call)的操作数前要加上'*'作为前缀
6、远程转移指令和远程子调用指令的操作码,在 AT&T 汇编格式中为 ljump和lcall
我们从生成的中间代码可以看出这几个特点。
我们再来看一段用AT&T汇编编写的helloworld程序
.section .data#初始化的变量
output:
.ascii "hello,world\n"
#要打印的字符串,.data为初始化值的变量。output是标签,指示字符串开始的位置,ascii为数据类型
.section .bss#未初始化的变量,由0填充的缓冲区
.lcomm num,20
#lcomm为本地内存区域,即本地汇编外的不能进行访问。.comm是通用内存区域。
.section .text#汇编语言指令码
.globl _start#启动入口
_start:
movl $4,%eax#调用的系统功能,4为write
movl $output,%ecx#要打印的字符串
movl $1,%ebx#文件描述符,屏幕为1
movl $12,%edx#字符串长度
int $0x80#显示字符串hello,world
movl $0,%eax
movl $num,%edi
movl $65,1(%edi)#A 的ascii
movl $66,2(%edi)#B 的ascii
movl $67,3(%edi)#C 的ascii
movl $68,4(%edi)#D 的ascii
movl $10,5(%edi)#\n的ascii
movl $4,%eax#调用的系统功能,4为write
movl $num,%ecx#要打印的字符串
movl $1,%ebx#文件描述符,屏幕为1
movl $6,%edx#字符串长度
int $0x80#显示字符串ABCD
movl $1,%eax#1为退出
movl $0,%ebx#返回给shell的退出代码值
int $0x80#内核软中断,退出系统
我们对上面这段汇编代码的结构和内容进行解说:
1、.section .data段存放着初始化的变量, .section .bss段存放着未初始化的变量
2、变量的定义采用以下格式:
变量名:
变量类型 变量值
上面代码中的output变量就是这么定义的
output:
.ascii "hello,world\n"
下面例子定义了多个变量
.section .data
msg:
.ascii “This is a text”
x:
.double 109.45, 2.33, 19.16
y:
.int 89
z:
.int 21, 85, 27
.equ a 8
其中,msg为字符符,x为双精度符点数,y和z为整数,a是一个特别的定义,它的是一个静态变量的定义,使用.equ 变量名 变量值来实现
3、.section .bss段中变量访问区域的定义规则为:
lcomm为本地内存区域,即本地汇编外的不能进行访问,而.comm是通用内存区域
比如上面的定义
.lcomm num,20
num为本地内存区域。
4、section .text段为汇编语言指令码,使用.globl _start指示_start标记后的代码为程序启动入口。
5、#表示注释,上面代码的其它部分均有注释,有汇编基础的程序员应很容易理解
变量的类型有以下几种:
.ascii 文本字符串
.asciz 以NULL结束的文本字符串
.byte 字节值
.double 双精度符点数
.float 单精度符点数
.int 32位整数
.long 32位整数
.octa 16位整数
.quad 8位整数
.short 16位整数
.single 单精度符点数
此外,AT&T汇编经常会涉及字节顺序反转,比较加载,交换,压入弹出所有寄存器等操作,以下例子涉及了这些操作,
每行代码都有详细的注释。
.section .text
data:
.byte 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01#8字节
.globl main
main:
movl $0x12345678,%edx
bswap %edx#反转字符顺序 ,结果为0x87654321
movl %edx,%eax
movl $1,%ebx
xadd %ebx,%eax#交换%eax和%ebx的值,并相加,结果放在目标位置%eax
cmpxchg %edx,%ebx#如果目标操作数%ebx等于%eax、16位是ax,8位是al,则把源操作数%edx的值加载到%eax中、16位
#是ax,8位是al,如果不等,则把目标操作数%ebx加到源操作数%edx加载到%eax中、16位是ax,8位是al
movl $2,%edx#高位
movl $3,%eax#低位
cmpxchg8b data#如果%edx:%eax组成的8字节值与目标值data匹配,则把%edx:%eax组成的8字节值传送到目标内存位置
#,否则将目标值data加载到%edx:%eax
pushad
popad
#pusha/popa 压入弹出所有16位通用寄存器
#pushad/popad 压入弹出所有32位通用寄存器
#pushf/popf 压入弹出EFLAGS寄存器的低16位
#pushf/popf 压入弹出EFLAGS寄存器的全部32位
AT&T汇编关于地址和取地址操作的示例代码如下:
.section .data
mynum:
.int 8
mygs:
.asciz "%x----%x----%x\n"
.section .text
.globl main
main:
leal mynum,%eax #将mynum地址复制到%eax
movl (%eax),%ebx#将%eax内地址所指内容复制到%ebx
movl mynum,%ecx#将mynum内容复制到%ecx中
push %ecx
push %ebx
push %eax
push $mygs
call printf
push $0
call exit
乘法和除法操作如下:
.section .data
.section .text
.globl main
main:
movl $2,%eax
movl $5,%ebx
mul %ebx#%eax*%ebx->%eax,无符号乘法
movl $-2,%eax
movl $5,%ebx
imul %ebx#%eax*%ebx->%eax,有符号乘法
#除法使用dev和idev(有符号)
引用来源:
1、http://www.ibm.com/developerworks/cn/linux/l-assembly/
扩展阅读:
《Professional Assembly Language》 作者: Richard Blum
如果转载请注明来源,如有错误之处,请及时指出。
分享到:
相关推荐
1. AT&T(ORL)人脸识别数据库: AT&T实验室的人脸识别数据库,也被称为ORL(Oxford Reasearch Laboratory)数据库,是早期广泛使用的公开人脸识别数据集之一。该数据库包含了40个人的不同面部图像,每个人有10个不同...
- **核心概念**:编写汇编语言程序需要熟悉一系列开发工具,包括编译器、链接器等。 - **实际应用**:通过亲手编写和调试汇编程序,可以增强对整个编译过程的理解。 - **1.3.3 提高算法开发技能** - **核心概念**...
Unix最初是为PDP-11架构设计的,随后被移植到了多种不同类型的处理器上,包括VAX和68000系列,这些架构上的汇编语言都采用了AT&T格式。当Unix最终移植到i386架构时,自然而然地继承了AT&T的汇编语言风格。 #### 五...
### IBM-PC汇编语言程序设计(第五版)——核心知识点解析 #### 一、书籍简介 《IBM-PC汇编语言程序设计(第五版)》是一部深入浅出地介绍IBM-PC环境下汇编语言程序设计的经典教材。本书旨在帮助读者理解和掌握汇编语言...
* 选择排序是一种简单的排序算法,它的思路是:进行 n-1遍循环,每次找到最大的数与当前最大的数交换。 * 选择排序的时间复杂度为 O(n^2),空间复杂度为 O(1)。 知识点6:汇编语言代码设计 * 汇编语言代码设计需要...
**汇编语言基础** 在IT领域,汇编语言是一种低级编程语言,它与机器语言密切相关,每一个指令都对应一个特定的机器码。IBM-PC汇编是针对IBM个人计算机系列(包括兼容机)的汇编语言,它主要用于对硬件进行直接控制...
这本书通过一系列的小代码实例,让读者能够亲手实践,从而更好地理解和运用汇编语言。 汇编语言的学习主要包括以下几个方面: 1. **基本概念**:首先,你需要了解汇编语言的基本构成,包括指令、寄存器、地址和...
#### 一、AT&T与Intel汇编语言的比较 在Linux系统中,汇编语言主要用于底层编程,特别是在处理硬件接口、性能优化等方面具有不可替代的作用。由于Linux系统的起源和发展背景,它主要采用了AT&T风格的汇编语言。这与...
1. **1-1 函数与调用栈** - **函数调用过程**:解释了函数调用时如何在内存中建立和清理调用栈的过程。 - **参数传递方式**:探讨了不同架构下的参数传递机制,如x86与x64架构的区别。 2. **1-2 循环** - **循环...
### GCC内联汇编基础知识点 #### 一、GCC内联汇编概述 **GCC内联汇编**是一种特殊的编程技术,允许开发人员在C/C++程序中直接嵌入汇编语言指令。这种方式有助于实现高性能的代码片段或访问特定硬件功能,而无需...
1. **x86指令集**:IBM-PC使用的是Intel 8088/8086系列处理器,它们的指令集构成了x86架构的基础。学习这本书需要理解各种指令,如数据传送指令、算术运算指令、逻辑运算指令、控制流程指令、输入输出指令等。 2. *...
1. **数组**:数组是最基础的数据结构,它在内存中存储同类型的元素序列。在C++中,数组可以是一维、二维或多维的,它们在内存中连续存储,可以通过索引来访问。 2. **链表**:链表不同于数组,它的元素在内存中...
《MATLAB实现遗传算法解决多车场开放式时间窗多商品VRP问题详解》 在物流配送、资源调度等领域,车辆路径规划(Vehicle Routing Problem, VRP)问题是一个经典的优化问题,它涉及到如何有效地安排车辆从一个或多个...
DES算法的主要流程包括初始置换(IP)、16轮迭代运算和逆初始置换(IP-1)。 初始置换(IP)的作用是将64位的明文按照特定规则重新排列,分为L0和R0两部分,每部分32位。IP置换规则是将原始64位数据重新排序,例如...
- **寄存器表示**:在AT&T汇编中,寄存器名前需加上`%`,如`%eax`,而在Intel汇编中则直接使用寄存器名,如`eax`。 - **立即数表示**:AT&T使用`$`前缀表示立即数,如`$1`,Intel则不需前缀,如`1`。 - **操作数...
教程一般会从基础概念入手,逐步介绍汇编语言的语法规则、指令集的使用方法以及程序设计的基本技巧。案例则是通过实际的编程示例来展示如何应用汇编语言解决具体问题,这些案例通常包括算法实现、系统功能调用、硬件...
第四章 MCS-51汇编语言程序设计主要探讨了如何使用汇编语言来编写针对MCS-51系列单片机的程序。汇编语言是一种低级编程语言,它的指令直接对应于计算机的机器指令,因此对于单片机的硬件控制具有很高的效率。相比...
AT89C51微控制器是一种广泛使用的8位微控制器,属于8051系列,由Atmel公司生产。它具备4KB的内部程序存储器(ROM),128字节的内部数据存储器(RAM),以及32个I/O口,具有串行通信接口和定时器/计数器等丰富的外围...
学习和理解易语言中的adler32算法汇编源码,不仅可以提升你在易语言编程方面的技能,还能加深对校验和算法的理解,以及对汇编语言如何与高级语言结合使用的认识。这对于系统级编程和性能优化工作非常有帮助。在实际...
汇编语言程序由一系列指令组成,每条指令对应于机器语言中的一个或多个字节。指令通常包含操作码(表示操作类型)和操作数(表示数据或地址)。例如,在 IA-32 架构下,“mov eax, 1”这条指令表示将数值 1 移动到...