📄 preproc.html
字号:
</pre></blockquote>
to
<blockquote class="code"><pre>
l_1<font color=#333399>:</font>
l_3<font color=#333399>:</font>
l_5<font color=#333399>:</font>
l_2<font color=#333399>:</font>
l_4<font color=#333399>:</font>
l_6<font color=#333399>:</font>
</pre></blockquote>
<br>
Another example:
<blockquote class="code"><pre>
macro ErrorList <font color=#333399>[</font>name<font color=#333399>,</font>value<font color=#333399>]</font>
<font color=#333399>{</font>
forward
ERROR_<font color=#333399>#</font>name <font color=#333399>=</font> value
<font color=#333399>}</font>
ErrorList <font color=#333399>\</font>
NONE<font color=#333399>,</font><font color=#339933>0</font><font color=#333399>,\</font>
OUTOFMEMORY<font color=#333399>,</font><font color=#339933>10</font><font color=#333399>,\</font>
INTERNAL<font color=#333399>,</font><font color=#339933>20</font>
</pre></blockquote>
to
<blockquote class="code"><pre>
ERROR_NONE <font color=#333399>=</font> <font color=#339933>0</font>
ERROR_OUTOFMEMORY <font color=#333399>=</font> <font color=#339933>10</font>
ERROR_INTERNAL <font color=#333399>=</font> <font color=#339933>20</font>
</pre></blockquote>
<br>
Of course there can be more than 2 group arguments:
<blockquote class="code"><pre>
macro a <font color=#333399>[</font>g1<font color=#333399>,</font>g2<font color=#333399>,</font>g3<font color=#333399>]</font>
<font color=#333399>{</font>
common
db g1
db g2
db g3
<font color=#333399>}</font>
a <font color=#339933>1</font><font color=#333399>,</font><font color=#339933>2</font><font color=#333399>,</font><font color=#339933>3</font><font color=#333399>,</font><font color=#339933>4</font><font color=#333399>,</font><font color=#339933>5</font><font color=#333399>,</font><font color=#339933>6</font><font color=#333399>,</font><font color=#339933>7</font><font color=#333399>,</font><font color=#339933>8</font><font color=#333399>,</font><font color=#339933>9</font><font color=#333399>,</font><font color=#339933>10</font><font color=#333399>,</font><font color=#339933>11</font>
</pre></blockquote>
to
<blockquote class="code"><pre>
db <font color=#339933>1</font><font color=#333399>,</font><font color=#339933>4</font><font color=#333399>,</font><font color=#339933>7</font><font color=#333399>,</font><font color=#339933>10</font>
db <font color=#339933>2</font><font color=#333399>,</font><font color=#339933>5</font><font color=#333399>,</font><font color=#339933>8</font><font color=#333399>,</font><font color=#339933>11</font>
db <font color=#339933>3</font><font color=#333399>,</font><font color=#339933>6</font><font color=#333399>,</font><font color=#339933>9</font>
</pre></blockquote>
<br><br><br>
<a name="cond"></a>
<b>7. Preprocessor conditionals</b><br>
In fact, there is no preprocessor conditional syntax in FASM (too bad). But
assembly directive <code>if</code> can be used in conjuction with preprocessor to
acheive same results as with preprocessor conditionals (but this way it
wastes more time and memory).<br><br>
As you know, <code>if</code> is assembly-time statement. That means statement is
checked after preprocessing, and that allows some special conditional
operators to work.<br><br>
I won't describe it's assembly-time behavior (conditional operators like
<code>&</code>, <code>|</code> etc), read FASM's docs for this. I will describe
only operators that are used with preprocessor here.
<br><br><br>
<a name="eq"></a>
<b>7.1. Operator <code>eq</code></b><br>
Simplest is <code>eq</code>. It just compares two symbols if they are same. Value of
<code>abcd eq abcd</code> is true, value of <code>abcd eq 1</code> is false etc. It is useful to
compare symbol that will be preprocessed, like:
<blockquote class="code"><pre>
STRINGS equ ASCII
if STRINGS eq ASCII
db <font color=#bb0000>'Oh yeah'</font><font color=#333399>,</font><font color=#339933>0</font>
else if STRINGS eq UNICODE
du <font color=#bb0000>'Oh yeah'</font><font color=#333399>,</font><font color=#339933>0</font>
else
display <font color=#bb0000>'unknown string type'</font>
end if
</pre></blockquote>
after preprocessing it will be
<blockquote class="code"><pre>
if ASCII eq ASCII
db <font color=#bb0000>'Oh yeah'</font><font color=#333399>,</font><font color=#339933>0</font>
else if ASCII eq UNICODE
du <font color=#bb0000>'Oh yeah'</font><font color=#333399>,</font><font color=#339933>0</font>
else
display <font color=#bb0000>'unknown string type'</font>
end if
</pre></blockquote>
so first condition (<code>ASCII eq ASCII</code>) is true, so only <code>db 'Oh yeah',0</code> will
get assembled.
<br><br>
Other case:
<blockquote class="code"><pre>
STRINGS equ UNICODE <font color=#777777>;only difference here, UNICODE instead of ASCII</font>
if STRINGS eq ASCII
db <font color=#bb0000>'Oh yeah'</font><font color=#333399>,</font><font color=#339933>0</font>
else if STRINGS eq UNICODE
du <font color=#bb0000>'Oh yeah'</font><font color=#333399>,</font><font color=#339933>0</font>
else
display <font color=#bb0000>'unknown string type'</font>
end if
</pre></blockquote>
after preprocessing it will be
<blockquote class="code"><pre>
if UNICODE eq ASCII
db <font color=#bb0000>'Oh yeah'</font><font color=#333399>,</font><font color=#339933>0</font>
else if UNICODE eq UNICODE
du <font color=#bb0000>'Oh yeah'</font><font color=#333399>,</font><font color=#339933>0</font>
else
display <font color=#bb0000>'unknown string type'</font>
end if
</pre></blockquote>
now first condition (<code>UNICODE eq ASCII</code>) will be false, second one (<code>UNICODE eq
UNICODE</code>) will be true and so <code>du 'Oh yeah',0</code> will get assembled.<br><br>
Better usage of this is checking macro arguments, like
<blockquote class="code"><pre>
macro item type<font color=#333399>,</font>value
<font color=#333399>{</font>
if type eq BYTE
db value
else if type eq WORD
dw value
else if type eq DWORD
dd value
else if type eq STRING
db value<font color=#333399>,</font><font color=#339933>0</font>
end if
<font color=#333399>}</font>
item BYTE<font color=#333399>,</font><font color=#339933>1</font>
item STRING<font color=#333399>,<font color=#bb0000>'aaaaaa'</font></font>
</pre></blockquote>
to
<blockquote class="code"><pre>
if BYTE eq BYTE
db <font color=#339933>1</font>
else if BYTE eq WORD
dw <font color=#339933>1</font>
else if BYTE eq DWORD
dd <font color=#339933>1</font>
else if BYTE eq STRING
db <font color=#339933>1</font><font color=#333399>,</font><font color=#339933>0</font>
end if
if STRING eq BYTE
db <font color=#bb0000>'aaaaaa'</font>
else if STRING eq WORD
dw <font color=#bb0000>'aaaaaa'</font>
else if STRING eq DWORD
dd <font color=#bb0000>'aaaaaa'</font>
else if STRING eq STRING
db <font color=#bb0000>'aaaaaa'</font><font color=#333399>,</font><font color=#339933>0</font>
end if
</pre></blockquote>
so only these two commands will get assembled:
<blockquote class="code"><pre>
db <font color=#339933>1</font>
db <font color=#bb0000>'aaaaaa'</font><font color=#333399>,</font><font color=#339933>0</font>
</pre></blockquote>
<br>
<code>eq</code> (like all other preprocessor operators) can also work with blank
arguments. That means, for example, that <code>if eq</code> is true, and
<code>if 5 eq </code> is
false etc.
Example macro:
<blockquote class="code"><pre>
macro mov dest<font color=#333399>,</font>src<font color=#333399>,</font>src2
<font color=#333399>{</font>
if src2 eq
mov dest<font color=#333399>,</font>src
else
mov dest<font color=#333399>,</font>src
mov src<font color=#333399>,</font>src2
end if
<font color=#333399>}</font>
</pre></blockquote>
<br><br>
<a name="eqtype"></a>
<b>7.2. Operator <code>eqtype</code></b><br>
Other operator is <code>eqtype</code>. It compares whether symbols are of same type.
Types are:
<li>individual quoted strings (those not being a part of numerical expression)
<li>floating point numbers
<li>any numerical expression (note that any unknown word will be treated as
label, so it also will be seen as such expression),
<li>addresses - the numerical expressions in square brackets (with size
operators and segment prefixes)
<li>instruction mnemonics
<li>registers
<li>size operators
<li>near/far operators,
<li>use16/use32 operators
<li>blank space
<br><br>
Example of macro which allows SHL instruction with memory variable as count,
like <code>shl ax,[myvar]</code>
<blockquote class="code"><pre>
macro shl dest<font color=#333399>,</font>count
<font color=#333399>{</font>
if count eqtype <font color=#333399>[</font><font color=#339933>0</font><font color=#333399>]</font> <font color=#777777>;if count is memory variable</font>
push cx
mov cl<font color=#333399>,</font>count
shl dest<font color=#333399>,</font>cl
pop cx
else <font color=#777777>;if count is of another type</font>
shl dest<font color=#333399>,</font>count <font color=#777777>;just use original shl</font>
end if
<font color=#333399>}</font>
shl ax<font color=#333399>,</font><font color=#339933>5</font>
byte_variable db <font color=#339933>5</font>
shl ax<font color=#333399>,[</font>byte_variable<font color=#333399>]</font>
</pre></blockquote>
to
<blockquote class="code"><pre>
if <font color=#339933>5</font> eqtype <font color=#333399>[</font><font color=#339933>0</font><font color=#333399>]</font>
push cx
mov cl<font color=#333399>,</font><font color=#339933>5</font>
shl ax<font color=#333399>,</font>cl
pop cx
else
shl ax<font color=#333399>,</font><font color=#339933>5</font>
end if
byte_variable db <font color=#339933>5</font>
if <font color=#333399>[</font>byte_variable<font color=#333399>]</font> eqtype <font color=#333399>[</font><font color=#339933>0</font><font color=#333399>]</font>
push cx
mov cl<font color=#333399>,[</font>byte_variable<font color=#333399>]</font>
shl ax<font color=#333399>,</font>cl
pop cx
else
shl ax<font color=#333399>,[</font>byte_variable<font color=#333399>]</font>
end if
</pre></blockquote>
and so, due to conditions, it will be assembled to
<blockquote class="code"><pre>
shl ax<font color=#333399>,</font><font color=#339933>5</font>
byte_variable db <font color=#339933>5</font>
push cx
mov cl<font color=#333399>,[</font>byte variable<font color=#333399>]</font>
shl ax<font color=#333399>,</font>cl
pop cx
</pre></blockquote>
Note that <code>shl ax,byte [variable]</code> wouldn't work with this macro, because
condition <code>byte [variable] eqtype [0]</code> isn't true, read further.
<br><br>
<code>eqtype</code> operands doesn't work only with two operands. It just compares
whether types of operands on left side and same to type of operands on right
side of <code>eqtype</code>. For example <code>if eax 4 eqtype ebx name</code>
is true (<code>name</code> is label and thus it is number too).<br><br>
Example of extending <code>mov</code> intruction so it allows moving between memory
variables:
<blockquote class="code"><pre>
macro mov dest<font color=#333399>,</font>src
<font color=#333399>{</font>
if dest src eqtype <font color=#333399>[</font><font color=#339933>0</font><font color=#333399>]</font> <font color=#333399>[</font><font color=#339933>0</font><font color=#333399>]</font>
push src
pop dest
else
mov dest<font color=#333399>,</font>src
end if
<font color=#333399>}</font>
mov <font color=#333399>[</font>var1<font color=#333399>],</font><font color=#339933>5</font>
mov <font color=#333399>[</font>var1<font color=#333399>],[</font>var2<font color=#333399>]</font>
</pre></blockquote>
will be preprocessed to
<blockquote class="code"><pre>
if <font color=#333399>[</font>var1<font color=#333399>]</font> <font color=#339933>5</font> eqtype <font color=#333399>[</font><font color=#339933>0</font><font color=#333399>]</font> <font color=#333399>[</font><font color=#339933>0</font><font color=#333399>]</font> <font color=#777777>;false</font>
push <font color=#339933>5</font>
pop <font color=#333399>[</font>var1<font color=#333399>]</font>
else
mov <font color=#333399>[</font>var1<font color=#333399>],</font><font color=#339933>5</font>
end if
if <font color=#333399>[</font>var1<font color=#333399>]</font> <font color=#333399>[</font>var2<font color=#333399>]</font> eqtype <font color=#333399>[</font><font color=#339933>0</font><font color=#333399>]</font> <font color=#333399>[</font><font color=#339933>0</font><font color=#333399>]</font> <font color=#777777>;true</font>
push <font color=#333399>[</font>var2<font color=#333399>]</font>
pop <font color=#333399>[</font>var1<font color=#333399>]</font>
else
mov <font color=#333399>[</font>var1<font color=#333399>],[</font>var2<font color=#333399>]</font>
end if
</pre></blockquote>
and assembled to
<blockquote class="code"><pre>
mov <font color=#333399>[</font>var1<font color=#333399>],</font><font color=#339933>5</font>
push <font color=#333399>[</font>var2<font color=#333399>]</font>
pop <font color=#333399>[</font>var1<font color=#333399>]</font>
</pre></blockquote>
Anyway, better (more readable) way to write such macro is to use <code>&</code>
operator (not described in this document, see FASM documentation), like:
<blockquote class="code"><pre>
macro mov dest<font color=#333399>,</font>src
<font color=#333399>{</font>
if <font color=#333399>(</font>dest eqtype <font color=#333399>[</font><font color=#339933>0</font><font color=#333399>])</font> & <font color=#333399>(</font>src eqtype <font color=#333399>[</font><font color=#33993
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -