vstart用法
如果一个程序有a,b两个段,那么如下的程序,最后2个字节存放的是b_label距离程序起始位置段a中mov ax,1
的偏移量
section a
mov ax,1
mov ax,2
a_label:
mov ax,3
section b
mov ax,4
mov ax,5
b_label:
mov ax,6
dw b_label ;此时该位置的值是0x12,说明距离段a的距离是18个字节
然而很多时候为了需要,我需要获取b_label距离当前段起始位置(段b中mov ax,4
)的偏移量,这个时候就需要加vstart=0
,代码如下
section a
mov ax,1
mov ax,2
a_label:
mov ax,3
section b vstart=0
mov ax,4
mov ax,5
b_label:
mov ax,6
dw b_label ;此时该位置的值是0x06,说明距离段b的距离是6个字节
上述代码是vstart=0,不过常用的也就是vstart=0,那如果是vstart=N呢?N表示顺着当前代码段向前推N个字节,然后从那个字节开始计算,比如vstart=0的时候,b_label=6,那么vstart=10,则b_label=16(十进制)
section.段名称.start
上文说如果一个段中出现了vstart,则该段内的标号都是相对于当前段的汇编地址,而不是相对于程序起始出的汇编地址,但是如何获得当前段的起始地址相对于程序起始处的汇编地址呢?使用nasm汇编语言的section.段名称.start
写法即可,例如下面的代码,在程序起始的前4个字节存放的内容是程序起始位置到段ccc的长度(以字节为单位)
section header vstart=0
main_segment dd section.ccc.start
section aaa vstart=0
mov ax,1
mov ax,1
mov ax,1
mov ax,1
section bbb vstart=0
times 10 dd 0xcccccccc
section ccc vstart=0
mov ax,1
mov ax,1
align用法
下面的代码,段b的代码是紧挨着段a的,因为```mov ax,1``占4个字节,所以段b从第5个字节开始
section a
mov ax,1 ;使用16进制查看器会发现占用位置0-3,前四个字节
section b
mov ax,2 ;使用16进制查看器会发现B8 02 00从字节04开始(实际第5个)
上述的代码会出现问题,因为段b是从汇编地址0x0004开始的,所以该段中所有的内容,如果基于当前段为段地址,那么必定出错,因为要转换成逻辑地址,需要将该地址右移4位,这样就会把0x0004中的4给挪没了,这也正是段地址必须要16字节对齐的原因,所以为了让段b16字节对齐(低4bit都是0),所以有了align关键字,这是NASM编译器自带的
section a
mov ax,1 ;使用16进制查看器会发现占用位置0-3,前四个字节,与上述例子相同
section b align=16
mov ax,2 ;使用16进制查看器会发现B8 02 00从字节10开始(实际第16个)
这样转换逻辑地址的时候,因为最右侧4bit是0,所以右移4位不会出问题