先熟悉nasm 【4】 ——SECTION和标签

   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    吉首

 

posted on 2012-08-25 17:35  weiweishuo  阅读(937)  评论(0编辑  收藏  举报

导航