V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
amiwrong123
V2EX  ›  程序员

如何理解汇编伪指令 equ 的使用?

  •  
  •   amiwrong123 · 2022-12-06 22:35:00 +08:00 · 1041 次点击
    这是一个创建于 736 天前的主题,其中的信息可能已经有所发展或是发生改变。
    ;===============================================================================
    SECTION core_data vstart=0                  ;系统核心的数据段
    ;-------------------------------------------------------------------------------
             pgdt             dw  0             ;用于设置和修改 GDT 
                              dd  0
    
             ram_alloc        dd  0x00100000    ;下次分配内存时的起始地址
    
             ;符号地址检索表
             salt:
             salt_1           db  '@PrintString'
                         times 256-($-salt_1) db 0
                              dd  put_string
                              dw  sys_routine_seg_sel
    
             salt_2           db  '@ReadDiskData'
                         times 256-($-salt_2) db 0
                              dd  read_hard_disk_0
                              dw  sys_routine_seg_sel
    
             salt_3           db  '@PrintDwordAsHexString'
                         times 256-($-salt_3) db 0
                              dd  put_hex_dword
                              dw  sys_routine_seg_sel
    
             salt_4           db  '@TerminateProgram'
                         times 256-($-salt_4) db 0
                              dd  return_point
                              dw  core_code_seg_sel
    
             salt_item_len   equ $-salt_4
             salt_items      equ ($-salt)/salt_item_len
    

    如上代码来自书籍 x86 从实模式到保护模式。equ 好像是 NASM 编译器的伪指令。

    这是 部分的内核代码,如上是,内核的数据段的描述。 里面有一个符号对应表:每个符号包括三部分:

    • 字符串
    • 函数在段内的偏移
    • 函数所在的系统例程段的选择子

    上面这个salt_items应该是 4 ,salt_item_len应该是 256+6=262 。

    1. salt_item_len equ $-salt_4这一句是可以理解为,计算出了salt_4标号后面的 db dd dw 的总和吗?但书中原话又说了$-salt_4是标号 salt_4 的汇编地址,如果是这样,那么这句也是不对的。

    2. salt_items equ ($-salt)/salt_item_len这一句则完全不理解,除法前面的是salt,即符号表的基地址,放到这里除 不太对吧?

    第 1 条附言  ·  2022-12-07 00:18:03 +08:00
    可能我这个标题起的不对,也许和这个伪指令 equ 没有关系。
    正确的标题应该是:如何正确使用汇编里面的标号。
    5 条回复    2022-12-07 12:15:36 +08:00
    chuckzhou
        1
    chuckzhou  
       2022-12-07 09:12:29 +08:00
    $ 是变化的,它等于当前地址,$-salt_4 就是当前地址减去 salt_4 的地址,得到的就是一个 item 的大小。
    ($-salt) 就是整个 salt 占用的空间,除以 salt_item_len 就算出来了一共有几个 salt item 。
    equ 就是定义一个符号,不占用空间。
    所以这两个 $ 其实相等。
    chrawsl
        2
    chrawsl  
       2022-12-07 09:27:30 +08:00
    equ 跟=伪指令大部分时候是一样的,都是用来给一个表达式或者任意文本起一个符号名称,但是在同一源代码文件中,equ 定义的符号不能被重复定义
    chrawsl
        3
    chrawsl  
       2022-12-07 09:30:48 +08:00
    $-salt_4 就是当前地址减去 salt_4 的地址,即 salt_4 的长度。下面就是求有多少个 salt 元素,伪指令不会影响 rip ,所以$不改变
    amiwrong123
        4
    amiwrong123  
    OP
       2022-12-07 10:09:50 +08:00
    @chuckzhou #1
    @chrawsl #3
    OK ,理解了。所以说,标号的话,就是代表的是 变量的起始地址。
    而$就是当前地址。

    而且,我理解,那这个 equ 的一条汇编地址,感觉就和“C 语言里面#define” 一样,在实际编译出来的二进制不存在这条指令。

    而且,进一步理解的话,那既然带 equ 的指令实际上不存在,那是不是说,在带 equ 的汇编指令里 使用符号$,其实是指 下一条不带 equ 的标号的地址(因为我代码没有给全,所以这条指令在帖子中 没有)。
    chrawsl
        5
    chrawsl  
       2022-12-07 12:15:36 +08:00
    @amiwrong123 确实跟 #define 一样,就是给特定的表达式起一个别名,编译前会由编译器进行全局替换
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2635 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:53 · PVG 22:53 · LAX 06:53 · JFK 09:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.