以上两节讲解了两个简单的示例程序, 从这一节开始, 就要接触到枯燥的细节了.
1. 在数据段中定义"全局变量"
在前面两讲中, 我们分别以.ascii
和.asciz
, 在数据段定义过字符串数据. 如下这样:
.section .data
output1:
.ascii "The processor Vendor ID is ‘xxxxxxxxxxxx‘\n"
output2:
.asciz "The processor Vendor ID is ‘%s‘\n"
我们可以把output1
与output2
理解为全局变量.
在数据段中定义数据元素需要用到两个语句:
- 标签语句. 用以给"变量"起名字, 即是
output1:
与output2:
- 命令语句. 用以给"变量"赋值.
数据的本质, 就是内存中的一段连续单元, 那么标签的本质是什么呢?
- 标签对cpu是没有意义的, 标签像极了高级语言中的变量名(单指值类型语言), 它本质上是内存区域的一个别名.
- 在汇编语言中, 标签是写给程序员看的. 而汇编代码经过编译链接后, 标签就会转换为内存中的地址.
除了标签之外, 还必须定义为数据元素保留多少字节. 保存内存的数量取决于数据的类型, 以及如果是多个重复数据的话, 还有数据的数量.
下面是数据声明命令:
命令 | 意义 |
---|---|
.ascii |
文本字符串 |
.asciz |
以\0结尾的文本字符串 |
.byte |
一个字节 |
.double |
一个双精度浮点数 |
.float |
一个单精度浮点数 |
.int |
32位整数 |
.long |
32位整数 |
.octa |
16(128位)字节整数 |
.quad |
8(64位)字节整数 |
.short |
16位整数 |
.single |
单精度浮点数, 同.float |
下面是正确示例:
.section .data
pi:
.float 3.1415926 # 定义了一个单精度浮点数
sizes:
.long 100, 150, 200, 250, 300 # 定义了一个数组, 数组中的元素均为32位整数, 数组共有5个元素
按数据段中, 各个标签数据定义的顺序, 各个数据元素将被按顺序存放在内存中. 带有多个值的元素(数组)也按顺序存放.
数据段中除了能够定义"变量"之外, 还能定义"静态符号". 所谓的"静态符号", 可以理解为类似于C语言中"宏值"的概念, 或者C++中"constexpr"的概念. 它不指代内存空间, 只是一个值的别名. 如下:
.section .data
.equ factor, 3
.equ LINUX_SYS_CALL, 0x80
.section .text
.globl _start
_start:
movl $LINUX_SYS_CALL, %eax # 实际上等价于 movl $0x80, %eax
2. 在bss段中声明缓冲区变量
C编程中很重要的一个基础技法就是, 做数据操作前先声明一个字符数组做缓冲区, 在读写过程中, 以缓冲区为中介, 暂存数据.
缓冲区的特点主要是:
- 一般情况下是一段有限长度的连续内存空间.
- 使用前不需要进行初始化
由于缓冲区使用前不需要进行初始化, 也无必要, 所以将缓冲区声明为全局变量或局部静态变量是一个很好的主意: 这种变量默认值为0, 且正因为C的机制使这种变量的初始化值为0, 这种变量在编译链接后的可执行文件中, 位于bss段, 不占用文件空间. bss段的size是为0字节!
我们在上一讲, 使用printf
输出cpu厂商信息的示例程序中, 就使用了一个声明了bss段中的缓冲区, 声明尺寸为12字节, 用于暂存厂商的12个字符, 代码片段如下:
.section .bss
.lcomm buffer 12
需要注意的是, bss段不占空间, 仅是指在程序编译链接后生成的二进制可执行文件中, bss段的长度为0. 但这个bss段依然在文件段表中有自己的段描述符. 并且在文件被操作系统装载, 成为进程后, bss段中声明的所有数据, 都会按照声明的长度在进程内存中占用对应的空间.
"未初始化的全局或局部静态变量"的声明, 和数据段中的"全局变量"声明, 写法不太一样. 变量名不是通过"标签语句"给出的, 而是在lcomm
或comm
命令中给出的. 命令后紧跟变量名, 再跟数据宽度
在bss段中声明变量有两个命令可以使用, 如下:
命令 | 意义 |
---|---|
.comm |
声明未初始化的数据的通用内存区域 |
.lcomm |
声明未初始化的数据的本地通用内存区域 |
语法为: .comm symbol, length
, 其中length
的单位是字节
.lcomm
中的l
的含义是local
, 即为本地的
, 即通过.lcomm
声明的变量, 无法被外部文件引用.
原文地址:https://www.cnblogs.com/neooelric/p/9693653.html