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

2022-12-06 22:35:00 +08:00
 amiwrong123
;===============================================================================
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,即符号表的基地址,放到这里除 不太对吧?

1029 次点击
所在节点    程序员
5 条回复
chuckzhou
2022-12-07 09:12:29 +08:00
$ 是变化的,它等于当前地址,$-salt_4 就是当前地址减去 salt_4 的地址,得到的就是一个 item 的大小。
($-salt) 就是整个 salt 占用的空间,除以 salt_item_len 就算出来了一共有几个 salt item 。
equ 就是定义一个符号,不占用空间。
所以这两个 $ 其实相等。
chrawsl
2022-12-07 09:27:30 +08:00
equ 跟=伪指令大部分时候是一样的,都是用来给一个表达式或者任意文本起一个符号名称,但是在同一源代码文件中,equ 定义的符号不能被重复定义
chrawsl
2022-12-07 09:30:48 +08:00
$-salt_4 就是当前地址减去 salt_4 的地址,即 salt_4 的长度。下面就是求有多少个 salt 元素,伪指令不会影响 rip ,所以$不改变
amiwrong123
2022-12-07 10:09:50 +08:00
@chuckzhou #1
@chrawsl #3
OK ,理解了。所以说,标号的话,就是代表的是 变量的起始地址。
而$就是当前地址。

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

而且,进一步理解的话,那既然带 equ 的指令实际上不存在,那是不是说,在带 equ 的汇编指令里 使用符号$,其实是指 下一条不带 equ 的标号的地址(因为我代码没有给全,所以这条指令在帖子中 没有)。
chrawsl
2022-12-07 12:15:36 +08:00
@amiwrong123 确实跟 #define 一样,就是给特定的表达式起一个别名,编译前会由编译器进行全局替换

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/900623

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX