[0x04] nasm汇编 [数据声明和定义]

在[0x02]和[0x03]中,举了一个打印hello, world!的例子,然后介绍了在nasm中的寄存器,以及一些特定的寄存器。这节介绍数据的定义和声明。

首先,要知道数据的长度,这就最基本的,就像在c语言中,char,short,int,long,long long,float,double,这些类型的字节长度是必须要知道的,在汇编中也一样。下面的表格展示了常用的数据类型。

类型 含义 长度(字节)
db 字节 1
dw 2
dd 双字 4
dq 四字 8

 

 

 

 

 

 

上面这些数据类型在nasm汇编中是最常用的。后面的文章会讲到浮点数,不过这是不常用的,因此,这里先不介绍。

下面是数据定义的例子test1.asm:

; test1.asm
; nasm -f elf64 -o test1.o test1.asm
; ld -o test1 test1.o

section .data
    var1 db 0x12               ; byte
    var2 db 0x12,0x34,0x56     ; 3 bytes
    var3 db 'hello, world!',0  ; string bytes
    var4 dw 0x1234             ; word
    var5 dd 0x12345678         ; double word
    var6 dq 0x1122334455667788 ; quad word

section .text
global _start
_start:
        
    mov rax, 60
    syscall

这里需要注意的是,声明的变量代表的是地址,而不是值,比如上面的var3,它的内容是后面字符串的首地址。var4也是一个地址,如果要使用0x1234,在汇编中,使用中括号,如mov ax, [var4]

var1是一个字节的整数

var2是包含3个字节整数的“数组”,这3个数在内存中是连续的

var3是一个字符串,每个字符占1个字节

var4是一个字的整数

var5是一个双字整数

var6是一个8字整数

这些是在数据段中声明和定义的。

在代码段中,调用了系统调用号为60的系统调用,这是退出调用。

有时候我们需要定义初始化的数组或未初始化的数组,test2.asm展示了如何做。

; test2.asm
; nasm -f elf64 -o test2.o test2.asm
; ld -o test2 test2.o

section .data
    var1: times 10 db 0
    var2: times 100 dw 0

section .bss
    buffer1: resb 64
    buffer2: resw 50
    buffer3: resd 10
    buffer4: resq 20

section .text
       
    mov rax, 60
    syscall

test2.asm中,在data段中,使用了times,times的作用是重复数据或指令。

var1: times 10 db 0 ; 表示重复10次字节,并且值为0

var2: times 100 dw 0 ; 表示重复100次字,并且值为0

这样可以解决定义初始化的数组。

而在.bss段中,使用了resb,resw这样的指令,它的作用也是重复,这是未对数据进行初始化。代码的具体含义很容易理解这里不再赘述。

为什么两种不同类型的数据存放在不同的段中呢?

这里我们要知道:.data段保存的是那些已经初始化了的全局静态变量和局部静态变量,而.bss段保存的是未初始化的全局变量和局部静态变量。(参考《程序员的自我修养--链接、装载与库》中的3.3.2和3.3.3节)

 

EQU: EQU的作用是定义常量,例如下面的部分代码

section .data
    var1 equ 2

使用equ声明的变量不能再次赋值,因为它定义的是常量,而且该变量不占用内存空间。如何验证?使用[readelf -t 可执行文件],-t选项展示各个段的细节,会发现,使用equ定义的变量不占用内存空间。

你可能感兴趣的:(汇编,nasm汇编)