曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4509|回复: 2
打印 上一主题 下一主题

定义数据元素

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2009-12-4 10:55:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
数据段

使用 .data 命令声明一个数据段。程序中定义的数据就放在数据段中,在这个段中声明的任何数据元素都保留在内存中并且可以被程序中的指令读取和写入。但还有一种称为 .rodata 的数据段,在此间定义的任何数据元素只能是只读的 (read-only),因此用了 ro 前缀。

在数据段中定义数据元素需要用到两个语句: 一个标签 和 一个命令。

标签是用来引用数据元素的标记,类似与和 C 语言中的变量。标签对处理器没有什么意义;它只是汇编器试图访问内存位置时用作引用指针的一个位置。

除了标签外,还必须定义要为数据元素保留多少字节,这通过使用一个汇编器命令来完成。这个命令只是汇编器为通过标签引用的数据元素保留特定数量的内存,简单的说就是声明数据的类型。声明数据类型的命令如下表:
命令
数据类型
.ascii
文本字符串
.asciz
以空字符结尾的文本字符串
.byte
字节
.double
双精度浮点数
.float
单精度浮点数
.int
32位整数
.long
32位整数(和 .int 相同)
.octa
16字节整数
.quad
8字节整数
.short
16位整数
.single
单精度浮点数(和 .float 相同)

保留内存数量取决于定义的数据类型,以及要声明的这个类型的项目数量。在声明命令之后,还必须定义一个 (或者多个) 默认值,这样把保留的内存位置中的数据设置为特定值。

例一:(声明一条字符串)
output:
.ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"
这么定义后,以后在程序中引用内存位置 output 时,汇编器知道要转到文本字符串开头的内存位置。

例二:(声明一个浮点数据)
pi:
.float 3.14159

例三:(一次定义多个值)
sizes:
.long 100,150,200,250,300
这样的定义如同数组,可以通过访问内存位置来访问这些数据,比如 sizes+4 访问 150 这个数,sizes+8 访问 200 这个数。

在数据段中,可以按照需要定义多个元素,定义时需要注意的是标签必须在定义数据的命令的前面:
.section .data
msg:
   .ascii "This is a test message"
factors:
   .double 37.45, 45.33, 12.30
height:
   .int 54
length:
   .int 62, 35, 47
按照数据段中定义数据元素的顺序,每个数据元素被存放到内存中。带有多个值的元素按照命令中列出的顺序存放,如下图所示:

注意:在程序中使用定义的数据元素要小心。程序并不知道是否正确地处理了数据,如果你定义了两个 16 位整数数据值,但是把其中一个作为 32 位整数值引用,汇编器仍然会读取必须的 4 字节内存,尽管这个值是错误的。

 

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
沙发
 楼主| 发表于 2009-12-4 11:00:23 | 只看该作者

定义静态符号

虽然数据段主要用于定义变量数据,但是也可以在这里声明静态数据符号。

.equ 命令用于把常量值设置为可以在文本段中使用的符号,设置方法如下:
.equ factor, 3
.equ LINUX_SYS_CALL, 0x80

经过设置之后,数据符号值不能在程序中改动的。.equ 命令可以出现在数据段的任何位置,但为了他人的阅读方便,最好在定义其他数据之前或者之后集中定义所有的数据符号。

应用静态数据元素时,必须在标签名称前面使用 $  符号,如:
movl $LINUX_SYS_CALL, %eax
把值付给 LINUX_SYS_CALL 的值传到 EAX 寄存器中。

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
板凳
 楼主| 发表于 2009-12-4 19:55:50 | 只看该作者

bss 段

在 bss 段中定义数据元素和在数据段中定义有些不同。在这里无须声明特定的数据类型,只要声明为所需目的的保留的原始内存部分即可。

GNU汇编器使用两个命令声明缓冲区,如下表所示:
命令
描述
.comm
声明未初始化的数据的通用内存区域
.lcomm
声明未初始化的数据的本地通用内存区域

虽然这两种区域的工作情况类似,但是本地通用内存区域是为不会从本地汇编代码之外进行访问的数据保留的。这两个命令的格式是:
comm symbol, length
其中,symbol 是赋给内存区域的标签,length 是内存区域中包含的字节数量,如下面所示:
.section .bss
.lcomm buffer, 10000
上面,把 10000 字节的内存区域赋值给 buffer 标签。在声明本地通用内存区域的程序之外的函数是不能访问它们的( 不能在 .global 命令中使用它们 ),所以这些区域通常也不为 ld 连接器所见。

在 bss 段中声明数据的一个好处是数据不包括到可执行程序中,而在数据段中定义的数据则会被包括到可执行程序里---因此必须对这些数据进行赋初值初始化。正是由于不对 bss 段中的数据进行初始化,所以所声明的内存区域也被保留到运行时使用。

下面分别比较一下 3 个程序的大小:

程序1代码
# size.s - A sample program to view the executable size

.section .text
.globl _start
_start:
    movl $1, %eax
    movl $0, %ebx
    int  $0x80
编译成可执行文件后大小为:
$ ls -l size
-rwxr-xr-x 1 beyes beyes 460 2009-12-04 19:47 size

程序2代码
# size2.s - A sample program to view the executable size

.section .bss
   .lcomm buffer, 10000

.section .text
.globl _start
_start:
    movl $1, %eax
    movl $0, %ebx
    int  $0x80
编译成可执行文件后大小为:
$ ls -l size2
-rwxr-xr-x 1 beyes beyes 575 2009-12-04 19:49 size2

程序3代码
# size3.s - A sample program to view the executable size

.section .data
buffer:
   .fill 10000

.section .text
.globl _start
_start:
    movl $1, %eax
    movl $0, %ebx
    int  $0x80
编译成可执行文件后大小为:
$ ls -l size3
-rwxr-xr-x 1 beyes beyes 10575 2009-12-04 19:50 size3
在 程序3 中使用 .fill 命令使汇编器自动创建 10 000 个数据元素,默认为每个字段创建一个字节,并且使用零来填充。

比较程序3 和 程序2 ,可见程序3的文件长度大大增加了,因为缓冲区的 10 000 个字节被添加到了可执行文件中。

关于 .fill 命令
.fill 命令的完整格式是:
.fill repeat, size, value
repeat 是要重复填充的次数
size 是每次填充时要填充多少个字节(不大于8,大于8也会是8)
value 用什么值来填充

修改一下上面的程序3代码:
.section .data
buffer:
   .fill 10000, 4, 8

output:
   .asciz "ouput buffer %d\\n"

.section .text
.globl main
main:
        pushl buffer
        pushl $output
        call printf
        addl $8, %esp
        pushl buffer+4
        pushl $output
        call printf
        addl $8, %esp

        movl $1, %eax
        movl $0, %ebx
        int  $0x80
输出
./size32
ouput buffer 8
ouput buffer 8
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-15 14:59 , Processed in 0.067966 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表