• 先熟悉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    吉首

     

  • 相关阅读:
    CentOS7 配置163 yum源(详细步骤)
    从构建分布式秒杀系统聊聊分布式锁
    互联网架构“高并发”
    互联网架构“高可用”
    FineCMS
    layUI表单事件监听-事件监听机制简化处理
    界面优雅的UI框架layUI
    如果OCX使用onmousedown和onmouseup来决定指令发送和指令停止会不会有问题?
    CSS字体库font-face用法及跨域问题
    RequireJS被外部调用
  • 原文地址:https://www.cnblogs.com/weiweishuo/p/3082641.html
Copyright © 2020-2023  润新知