1,nasm下,自定义段默认按4byte对齐。
手册上说,“ 通过在段定义行的后面加上'ALIGN'限定符实现的。比如:section .data align=16 它切换到段'.data',并指定它必须对齐到 16 字节边界。” 我也在自定义段里加上align 16,发现编译生成的代码仍按照4byte对齐。很诡异。
2,再说标签。
看下面一段代码(可正常运行),它们被写到mbr,会被加载到0x7c00处
----------------------------
org 0h
s:mov ax,s
inc ax
.....
---------------------------
问:编译器会怎么处理标签s呢?是将其翻译成真实的物理地址,还是偏移地址呢?
要回答这个问题,只需要将编译后的二进制文件反汇编,看看mov ax,s这句便可,下面是我在bochs上的反汇编结果:
----------------------------------------------------------------------------
00007c00: ( ): mov ax, 0x0000 ; b80000
----------------------------------------------------------------------------
mov ax,s被翻译成mov ax, 0x0000。显然,编译器处理标签时,是将标签翻译成对应的“偏移地址”——有人要问了,你这“偏移地址”说的不明不白的,究竟是相对哪儿的偏移地址呢?是相对于源代码的第一条指令的偏移么? 这就得提到org指令了,当org的操作数是0,这“偏移地址”就是相对于程序开头儿第一条指令,若org的操作数是个非0常数xx,这“偏移地址”就要额外的加上xx。方便理解,这里再举个例子,将上面的代码变一下:
----------------------------
org 10h
s:mov ax,s
inc ax
.....
---------------------------
反汇编可看到:
-----------------------------------------------------------------------------
0000:7c00 (unk. ctxt): mov ax, 0x0010 ; b81000
----------------------------------------------------------------------------
因此得到结论:标签被翻译成“偏移地址”。
3,$和$$是特殊的标签:$$表示当前section第一行的相对“偏移地址”,$表示当前行的相对“偏移地址”。举个小例子,看代码:
-----------------------------
%include "./rw_floppy.mac"
org 7c00h
entrance:read_floppy_side_o_sector_total_destsa_destea 0,0,0,2,30,0,7e00h ;这是我自己定义的宏,负责将第二个扇区的代码加载到0x0000:0x7e00处。
jmp main_entrance
times 510-($-$$) db 0
dw 0aa55h ;第一个扇区填满
main_entrance: ;此处代码从第二个扇区开始
[SECTION .test1 ]
mov ax,$
mov ax,$
mov ax,$$
mov ax,$$
[SECTION .test2]
mov ax,$
mov ax,$
mov ax,$$
mov ax,$$
----------------------------
看反汇编后的结果:
------------------------------
00007e00: ( ): mov ax, 0x7e00 ; b8007e
00007e03: ( ): mov ax, 0x7e03 ; b8037e
00007e06: ( ): mov ax, 0x7e00 ; b8007e
00007e09: ( ): mov ax, 0x7e00 ; b8007e
00007e0c: ( ): mov ax, 0x7e0c ; b80c7e
00007e0f: ( ): mov ax, 0x7e0f ; b80f7e
00007e12: ( ): mov ax, 0x7e0c ; b80c7e
00007e15: ( ): mov ax, 0x7e0c ; b80c7e
-----------------------------
不用多说,结果非常清楚了
4,发现一个问题:nasm中不能跨段执行标签的减法运算。看代码:
---------------------------
org 7c00h
entrance:read_floppy_side_o_sector_total_destsa_destea 0,0,0,2,30,0,7e00h
jmp main_entrance
times 510-($-$$) db 0
dw 0aa55h
main_entrance:
[SECTION .test1 ]
s1:db 0
[SECTION .test2]
s2:db 0
s3:mov ax,s3-s1 ;注意这儿,s1和s3是不同SECTION的标签
--------------------------
上面代码不能通过编译,会报错error: invalid operand type
但下面代码就可以通过编译:
---------------------------
org 7c00h
entrance:read_floppy_side_o_sector_total_destsa_destea 0,0,0,2,30,0,7e00h
jmp main_entrance
times 510-($-$$) db 0
dw 0aa55h
main_entrance:
[SECTION .test1 ]
s1:db 0
[SECTION .test2]
s2:db 0
s3:mov ax,s3-s2 ;注意这儿,s2和s3是相同SECTION的标签
--------------------------
我猜测是nasm禁止跨段做标签的减法,不知道有没有朋友也遇到此情况。
2012,8,25 吉首