NASM手册阅读笔记(5) - 预处理器之上下文栈
上下文堆
解释
就是一个在编译期间由编译器维护的堆栈
之前说了预处理器的作用是在编译阶段执行一些代码,以简化或者增强汇编代码的能力,就像汇编代码本身执行的过程中需要一个堆栈存储一些信息一样,预处理器的指令在运行过程中也是需要存储一些信息的,那么这个上下文栈就是存储信息的地方
但是它比堆栈更强大,堆栈是只能存储一个值,而上下文栈是可以在每层存储很多信息
类比的话就是堆栈的每一层都是一个有名字的容器,你可以在每一层的容器里存储各种各样的东西。
%push / %pop
格式
%push 随便起个名字
%pop
说明
%push foobar 就是添加一个名字到foobar的容器到栈顶,以后可以使用可以使用宏 %ifctx foobar来判断
%pop 就是删除并销毁栈顶容器
%$ / %$$ / %$$ /.....
格式
%$LABEL
%$$LABEL
%$$$LABEL
说明
这一些列标识符就相当于取堆栈中的容器的意思,%$ 就是去栈顶元素 %$$ 取相对于栈顶的第二个元素,以此类推
所以也有点 vector 的下标的意思
可以用它来定义子标签(本地标签)和子宏(本地宏)
%$LABEL1: 将当前位置在栈顶容器里定义一个子标签叫 LABLE1
%$$LABEL2: 将当前位置在相对于栈顶的第二个容器里定义一个子标签叫 LABLE2
%$$$LABEL3: 将当前位置在相对于栈顶的第三个容器里定义一个子标签叫 LABLE3
%define %$localmacro 将当前位置在栈顶容器里定义一个宏叫 localmacro
之后只要保持栈顶相同,那么就可以在任意地方直接使用%$LABEL 进行转跳
比如
%macro repeat 0
%push repeat ; 增加一个容器,命名为repeat
%$begin: ; 将当前位置在新增加的容器里定义一个子标签,我们可以认为实际就是定义了一个repeat.begin标签
%endmacro
%macro until 0
jmp %$begin ; 转跳到 %$begin ( repeat.begin )
%pop ; 这里栈顶发生变化了,所以不能在使用%&begin了,因为repeat容器没了
%endmacro
%repl
对栈顶容器进行改名,他只改变名字并没有实际操作容器内容,所以之前在容器中的内容还是安全的
预支相比的
%pop
%push XXX
指令也能起到改名的作用,但是在调用%pop的时候容器中的内容就被销毁了,所以这是不安全的。当然也可以把它当成重置命令来用。