MASM中的向前引用(Forward Reference)
当程序需要引用尚未定义的变量或标号时,编译器会如何处理呢,这就涉及到向前引用(Forward Reference)的概念。
一、Forward Reference的概念
程序引用到之前尚未定义的变量(Variable)、标号(Label)、段(Segment)或其他标识符(Symbol),编译器会如何处理?MASM编译器对源码执行两遍扫描,编译器第一遍会假设该引用的类型,为该类型留出存储空间,然后在第二遍将该引用的地址或数据填充正确。
这里就会产生2个问题:
1、编译器假设的类型与实际类型不一致,会导致预留的空间太大或太小,太大会使程序变大或导致执行效率降低,太小则无法正常编译通过。如jmp target,target默认假设为near,编译器预留空间为3个字节;但实际target为far,则需要5个字节。
2、编译器在处理前置引用时会降低编译效率,因此尽量不要发声向前引用。
二、向前引用标号(Label)
jmp target;Forward Reference
...
...
target:
1、指令跳转,编译器会假设jmp为near jmp,如果jmp是short或far,需要明确指定,如far ptr。
2、子程序调用,编译器会假设call myproc为near(无论子程序是通过proc还是label的方式定义),如果proc定义为far,则需明确指定类型:call far ptr myproc。
3、如果标号为外部extrn引入,则不需要指定类型,直接jmp target或call myproc即可。
三、向前引用变量(Variable)
1、变量引用无论是否为向前引用,都需要明确类型,只是数据段寄存器无法确定。编译器会假设段寄出去为:DS,可通过段前缀进行指定:ES:myvar。
2、如果是segname:myvar或groupname:myvar的引用形式,且该段也未提前定义,则需将段加入到某个组(group)中,让编译器知道该段或组确实存在。
四、注意事项
1、.386代码模式中,条件转移指令(如jl、jb等)和far jmp与.286及之前,所占用的字节数不一致,即在386代码模式中,条件转移指令不再限制为short jmp(注意.386与.model的顺序)。
2、如果不是向前引用,jmp short和jmp near不用区分,编译器会根据实际情况判断,因此只需要jmp target即可,跨段跳转才需要明确指定jmp far ptr target。
3、proc如果不是向前引用,只需call myproc即可,不区分near和far,编译器会自动判断。