为什么是汇编语言
本文关键词:汇编语言,由笔耕文化传播整理发布。
为什么是汇编语言 Posted on
语言的编译过程就是把高级语言转换成计算机能够理解的二进制机器指令的过程。这种转换会产生一些效率不是很高的代码。所以对一些效率要求高,或者对性能影响大的代码都会直接用低级的汇编语言来编写。
汇编器是专门用来把低级汇编语言编译成机器码的二进制程序或者目标文件。
基于每个体系设计的cpu都会有其对应的汇编语言,比如x86,arm
C语言的编译过程
预处理->编译(得到.s)->汇编(得到.o)->链接 (得到二进制)
每一个c源文件都会得到一个目标文件(.o),然后会把这些相关的目标文件链接成一个二进制文件。
其实每一种高级语言都会被编译成汇编语言,最后得到二进制文件,所以了解汇编语言是很重要的。
AT&T汇编用GNU GAS编译,intel 汇编用NASM编译
数据在内存中存放的一个重要特点:高位对应高地址,低位对应低地址
立即数
立即数相当于高级语言中的常量,不用存储在寄存器中,可以在表达是中直接使用
比如
movl $0x04,%ebx ;就相当于把0x04这个值放入寄存器ebx
movl 0x04,%ebx ;就相当于把从内存地址0x04开始的4个字节的内容放入寄存器ebx
而在intel汇编中,立即数是不需要任何符号的,取内存里面的值要加[ ]
movl %ebp,%eax #把ebp里面的内容放到eax里面
movl -4(%ebp),%eax #从(ebp-4)这个地址开始的4个字节的内容放到eax里面,注意section:disp(base, index, scale)这种写法本身就表示地址,不是立即数,就只能取值
间接操作数含有实际操作数的地址值,AT&T语法通过在一个操作数前添加*来指定一个间接操作数。只有在间接跳转/调用指令时才使用间接操作数。
jmp *%ebx #ebx的值是跳转的目标位置
jmp *(%ebx) #从ebx值的指定的地址处读取跳转的目标位置
在一个目标文件中text区从地址0开始,,随后是data区,然后是bss区
每个区都有意个位置计数器,它会对每个汇编进该区的字节进行计数;.align可以改变位置计数器的值
bss区用于存放未被初始化的变量或者作为局部公共变量存储空间
.lcomm用于在bss区定义一个符号
.comm用于在bss区定义一个公共符号
在程序运行之前不能在bss区放置数据,因为程序开始之前,所有bss区的内容都会被清零
absolute区在重定位后地址保持不变,两个目标文件中absolute区中地址相同的数据会因为重叠而被一个覆盖
特殊符号'.'表示as汇编的当前地址因此 mylab: .long . 表示把mylab它自己所处地址的值,给'.'赋值如同‘.org'的作用,因此 .=.+4和 .space 4一样
语句
可以是只含空格 制表符 换行符的空行,也可以是1)赋值语句 2)伪操作符语句3)机器指令语句
1)赋值语句
BOOTSEG = 0x70C0
2)伪操作符语句
以一个点开始的汇编语句叫做,汇编命令(伪指令,指示符)。伪指令的地址是点符号出现处,机器指令第一个字节的位置。它本身不产生任何代码。
.globl begtext, begdata, begbss, endtext, enddata, endbss
3)机器指令
每个机器指令前面都可以有一个标号。机器指令可以由 标号 + 指令助记符 + 操作数 三个字段组成。
任何标号定义都会取用位置计数器的当前值。标号本身不占内存,它的地址是后面的机器指令的第一个字节的位置,我通过gdb的info line查看了。(位置计数器我还是不太清楚到底是干什么的)
AT&T汇编语句以换行符或者;结束,最后的一个语句必须以换行符结束
PS:intel汇编都是以换行符结束的,所以intel汇编可以用;来注释
注释
intel 汇编的注释是!或者;
AT&T的注释是shell 风格的#或者c风格/* */或者c++风格的//
汇编语言的一个突出优点就是可以使用符号(symbol),正是因为有了符号汇编语言才变得容易理解,便于记忆(相对于机器指令而言)
标号是符号的一种
movz: 零扩展,高位用0补齐
movb $0x80,%bl
movzbw %bl,%ax
ax就变成了0x0080
movs: 符号扩展,高位用原最高位补齐
movb $0x80,%bl
movsbl %bl,%ax
ax就变成了0xFF80
本文关键词:汇编语言,由笔耕文化传播整理发布。
本文编号:510348
本文链接:https://www.wllwen.com/wenshubaike/dxkc/510348.html