AT&T伪指令 以及对于CFI CFA的解释

包含了所有我遇到的伪指令,网上这种资料比较少,所以整理记录下来。阅读本文善用Ctrl+F。

第一部分 无序

.section指示把代码划分成若干个段(section),程序被操作系统加载时,每个段被加载到不同的地址,具有不同的读写执行权限。

.data段保存程序的数据是可读写的,C程序的全局变量也属于.data段。上边的程序没定义数据所以.data是空的。

.data subsection
该汇编命令通知as把随后的语句汇编到编号为subsection的data子区中。如果省略编号,则默认使用编号0。编号必须是绝对值表达式。

.text段保存代码,是只读和可执行的,后面那些指令都属于这个.text段。

_start是一个符号(Symbol),符号在汇编程序中代表一个地址,可以用在指令中,汇编程序经过汇编器的处理后所有的符号都被替换成它所代表的地址值。在C中我们可以通过变量名访问一个变量,其实就是读写某个地址的内存单元,我们通过函数名调用一个函数其实就是调转到该函数的第一条指令所在的地址,所以变量名和函数名都是符号,本质上是代表内存地址的。

.globl指示告诉汇编器_start这个符号要被链接器用到,所以要在目标文件的符号表中给它特殊标记。_start就像C程序的main函数一样特殊是整个程序的入口,链接器在链接时会查找目标文件中的_start符号代表的地址,把它设置为整个程序的入口地址,所以每个汇编程序都要提供一个_start符号并且用.globl声明。如果一个符号没有用.globl指示声明这个符号就不会被链接器用到。

.long指示声明一组数,每个数32位,相当于C数组。数组开头有个标号data_items,**汇编器会把数组的首地址作为data_items符号所代表的地址,data_items类似于C中的数组名。**data_items这个标号没有.globl声明是因为它只在这个汇编程序内部使用,链接器不需要知道这个名字的存在。除了.long之外常用的声明:

.byte,也是声明一组数,每个数8位

.ascii,例: .ascii “Hello World”,声明了11个数,取值为相应字符的ASCII码。和C语言不同的是这样声明的字符串末尾是没有’\0’字符的。

.align abs-expr1, abs-expr2, abs-expr3
.align是存储对齐汇编命令,用于在当前子区中把位置计数器值设置(增加)到下一个指定存储边界处。第1个绝对值表达式abs-expr1(Absolute Expression)指定要求的边界对齐值。对于使用a.out格式目标文件的80x86系统,该表达式值是位置计数器值增加后其二进制值最右面0值位的个数,即是2的幂值。例如,".align 3"表示把位置计数器值增加到8的倍数上。如果位置计数器值本身就是8的倍数,那么就无需改变。但是对于使用ELF格式的80x86系统,该表达式值直接就是要求对齐的字节数。例如".align 8"就是把位置计数器值增加到8的倍数上。
第2个表达式给出用于对齐而填充的字节值。该表达式与其前面的逗号可以省略。若省略,则填充字节值是0。第3个可选表达式abs-expr3用于指示对齐操作允许填充跳过的最大字节数。如果对齐操作要求跳过的字节数大于这个最大值,那么该对齐操作就被取消。若想省略第2个参数,可以在第1和第3个参数之间使用两个逗号。

.file指明源文件

第二部分 分类

一、类型定义
.byte : 定义定长1字节整型,8位;
.short : 定义定长2字节整型,16位;
.word : 定义定长2字节整型,16位;
.hword : 定义定长2字节整型,16位;
.2byte : 定义定长2字节整型,16位;
.int : 定义定长4字节整型,32位;
.long : 定义定长4字节整型,32位;64位程序中是定长8字节,64位;
.4byte : 定义定长4字节整型,32位;
.quad : 定义定长8字节整型,64位;
.octa : 定义定长16字节整型,128位;
.uleb128: 定义变长无符号整数,最多128位,16字节;
.sleb128: 定义变长有符号整数,最多128位,16字节;
.single : 定义定长单精度浮点数,4字节,32位;
.float : 定义定长单精度浮点数,4字节,32位;
.double : 定义定长双精度浮点数,8字节,64位;
.ascii : 定义非空字符’\0’(即:二进制0)结束的字符串;
.asciz : 定义以空字符’\0’(即:二进制0)结束的字符串;
.string : 定义以空字符’\0’(即:二进制0)结束的字符串;

二、对象定义
ELF格式的目标文件,用于定义函数或变量的伪指令是.type;
格式:
.type name, type_description

这个伪指令指令支持以下五种写法:
.type , #function
.type , #object

.type , @function
.type , @object

.type , %function
.type , %object

.type , “function”
.type , “object”

.type STT_FUNCTION
.type STT_OBJECT

三、运算符
1、算术运算符

+  : 加法
-  : 减法
*  : 乘法
/  : 除法
%  : 取余

2、比较运算符

== : 等于
<> : 不等于
<  : 小于
<= : 小于或等于
>  : 大于
>= : 大于或等于

3、位运算符

|  : 按位或
&  : 按位与
^  : 按位异或
<< : 按位左移
>> : 按位右移

4、逻辑运算符:

&& : 逻辑与
|| : 逻辑或
!  : 逻辑反

四、常量定义

.set symbol,expr  : 把表达式expr的值赋值给符号symbol;
.equ symbol,expr  : 把表达式expr的值赋值给符号symbol;
.equiv symbol,expr: 把表达式expr的值赋值给符号symbol,如果symbol已经被定义,则触发一个错误;
symbol = expr     : 把表达式expr的值赋值给符号symbol;

五、特殊符号

圆点符号".": 这个符号引用的是当前正在被汇编器汇编的指令或数据的地址;
比如:
var: .long .     ;定义变量var,其初始值是其自身的地址;
len: .long .-var ;定义变量len,其初始值是变量var占用的字节数(当前变量的地址-变量var的地址);
.=.+4            ;从当前位置开始预留4个字节的空间;等价于".space size,0";

六、其它

.space size[,fill]:
申请分配size个字节的空间,并用fill来填充这size个字节的空间,如果省略fill,默认将使用0填充;等价于.skip指令;技巧".=.+size";
.skip size[,fill]:
申请分配size个字节的空间,并用fill来填充这size个字节的空间,如果省略fill,默认将使用0填充;等价于.space指令;技巧".=.+size";
.comm symbol,length:
定义普通符号symbol,并为其预留length个字节;
.lcomm symbol,length:
定义本地普通符号symbol,并为其预留length个字节;
.align expr:
使字节块首地址按照expr指定的字节边界对齐;
.weak symbol:
该指令为symbol设置弱属性,如果symbol不存在,则创建symbol;
.print "string":
汇编源码的过程中,遇到伪指令.print时,会打印字符串string的内容;字符串必须使用双引号括起来;
.size name,expr:
把表达式expr的值作为符号name的大小;
.extern:
声明外部符号;
.globl/.global:
定义全局符号;
.err "string":
打印错误信息;
.fail expr:
生成一个错误或警告信息;如果表达式expr的值大于等于500,as汇编器将打印一个警告信息;如果表达式expr的值小于500,as汇编器将打印一个错误信息,信息中将包含表达式expr的值;
.end:
结束汇编源代码的汇编过程,该指令之后的内容都会被汇编器忽略;功能与MASM中的END指令类似;
.rept N:
把其源代码块重复汇编N次;
例如:
array:
  .rept 4
    .long 0
  .endr
此语句块是定义一个具有4个long型元素的数组array;
把.rept指令展开后,其等价的语义为:
array:
  .long 0
  .long 0
  .long 0
  .long 0

第三部分 CFI伪指令

.cfi_startproc 用在每个函数的开始,用于初始化一些内部数据结构
.cfi_endproc 在函数结束的时候使用与.cfi_startproc相配套使用

第四部分 对于CFI和CFA的解释

CFI stands for call frame information. It’s the way the compiler describes what happens in a function. It can be used by the debugger to present a call stack, by the linker to synthesise exceptions tables, for stack depth analysis and other things like that.

CFI代表调用帧信息,这是编译器描述函数中发生的事情的方式。调试器可以用它来显示栈调用,连接器可以合成异常日志,用于堆栈深度分析或者别的事情。

Effectively, it describes where resources such as processor registers are stored and where the return address is.

它有效的描述了处理器寄存器等资源存储在哪里以及返回地址在哪里。

CFA stands for call frame address, which mean the address the stack pointer location of the caller function. This is needed to pick up information about the next frame on the stack.

CFA表示调用帧地址,表示调用函数的堆栈指针位置。 这需要收集有关堆栈上的下一个帧的信息。

可能你还是不太理解什么叫做:呼叫帧信息(CFI),实际上就是记录调用栈的信息用于后续debug的一种优化方式。可以关掉,没有影响。
可以看看下面这个回答。
在这里插入图片描述

转载声明:
1.https://www.cnblogs.com/orlion/p/5765339.html
2.https://www.cnblogs.com/wzf365/p/3381780.html
3.https://stackoverflow.com/questions/24462106/what-do-the-cfi-directives-mean-and-some-more-questions

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值