simulating_20assembler_20macros
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
simulating_20assembler_20macros [2018/03/31 13:19] – external edit 127.0.0.1 | simulating_20assembler_20macros [2024/01/05 00:21] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
=====Simulating assembler macros===== | =====Simulating assembler macros===== | ||
- | //by Richard Russell, December 2008//\\ \\ //This article supplements the information in the main Help documentation under [[http:// | + | //by Richard Russell, December 2008//\\ \\ //This article supplements the information in the main Help documentation under [[http:// |
+ | |||
+ | <code bb4w> | ||
DEF FNabs | DEF FNabs | ||
[OPT 0 | [OPT 0 | ||
Line 9: | Line 11: | ||
] | ] | ||
= pass% | = pass% | ||
- | Now, whenever you want to calculate the absolute value of eax you can do so in your main assembler code as follows:\\ \\ | + | </ |
+ | |||
+ | Now, whenever you want to calculate the absolute value of eax you can do so in your main assembler code as follows: | ||
+ | |||
+ | <code bb4w> | ||
DIM code% 100, L% -1 | DIM code% 100, L% -1 | ||
FOR pass% = 8 TO 11 STEP 3 | FOR pass% = 8 TO 11 STEP 3 | ||
Line 22: | Line 28: | ||
NEXT pass% | NEXT pass% | ||
END | END | ||
+ | </ | ||
+ | |||
Here **FNabs** returns the current value of **pass%**, so in the main assembler loop the **OPT FNabs** pseudo-instructions simply set the assembler options (to what they already were). However the called function itself emits the opcodes corresponding to the absolute value calculation. You can see the effect by looking at the listing generated (note that the **OPT 0** in FNabs prevents any listing being generated there):\\ \\ | Here **FNabs** returns the current value of **pass%**, so in the main assembler loop the **OPT FNabs** pseudo-instructions simply set the assembler options (to what they already were). However the called function itself emits the opcodes corresponding to the absolute value calculation. You can see the effect by looking at the listing generated (note that the **OPT 0** in FNabs prevents any listing being generated there):\\ \\ | ||
1002181A | 1002181A | ||
Line 29: | Line 37: | ||
1002181F 99 33 C2 2B C2 OPT FNabs | 1002181F 99 33 C2 2B C2 OPT FNabs | ||
10021824 | 10021824 | ||
- | Another way in which this facility can be used is to extend the assembler to handle instructions which are not supported natively. For example the instruction **SYSENTER** is available only on the Pentium Pro and later range of processors, and is therefore not supported in the //BBC BASIC for Windows// assembler. The following user-defined function can be used to ' | + | Another way in which this facility can be used is to extend the assembler to handle instructions which are not supported natively. For example the instruction **SYSENTER** is available only on the Pentium Pro and later range of processors, and is therefore not supported in the //BBC BASIC for Windows// assembler. The following user-defined function can be used to ' |
+ | |||
+ | <code bb4w> | ||
DEF FNsysenter | DEF FNsysenter | ||
[OPT 0 | [OPT 0 | ||
Line 36: | Line 46: | ||
] | ] | ||
= pass% | = pass% | ||
- | Now, whenever you require to call the SYSENTER instruction, | + | </ |
+ | |||
+ | Now, whenever you require to call the SYSENTER instruction, | ||
OPT FNsysenter | OPT FNsysenter | ||
- | A similar technique can be used when the instruction takes a parameter, for example a register name:\\ \\ | + | |
+ | A similar technique can be used when the instruction takes a parameter, for example a register name: | ||
+ | |||
+ | <code bb4w> | ||
DEF FNfcmovb(reg$) | DEF FNfcmovb(reg$) | ||
[OPT 0 | [OPT 0 | ||
Line 45: | Line 61: | ||
] | ] | ||
= pass% | = pass% | ||
- | This implements the **FCMOVB** instruction which takes as a parameter an FPU register name (**st0** to **st7**). The routine automatically adjusts the emitted opcode according to the register specified (for simplicity the operand is not checked for validity, but it could be):\\ \\ | + | </ |
+ | |||
+ | This implements the **FCMOVB** instruction which takes as a parameter an FPU register name (**st0** to **st7**). The routine automatically adjusts the emitted opcode according to the register specified (for simplicity the operand is not checked for validity, but it could be): | ||
OPT FNfcmovb(" | OPT FNfcmovb(" | ||
+ | |||
With care the technique can be extended to instructions which take more complex operands.\\ \\ | With care the technique can be extended to instructions which take more complex operands.\\ \\ | ||
==== Using labels in macros ==== | ==== Using labels in macros ==== | ||
- | \\ If you need to use labels in the assembler code generated by a macro, care is needed to prevent a **Multiple label** error occurring when the macro is called more than once. If the labels are genuinely ' | + | \\ If you need to use labels in the assembler code generated by a macro, care is needed to prevent a **Multiple label** error occurring when the macro is called more than once. If the labels are genuinely ' |
+ | |||
+ | <code bb4w> | ||
DEF FNincarray | DEF FNincarray | ||
LOCAL label | LOCAL label | ||
Line 59: | Line 81: | ||
] | ] | ||
= pass% | = pass% | ||
- | Often you can rearrange code to ensure all references to labels are ' | + | </ |
+ | |||
+ | Often you can rearrange code to ensure all references to labels are ' | ||
+ | |||
+ | <code bb4w> | ||
DEF FNsimplisticabs(i%) | DEF FNsimplisticabs(i%) | ||
PRIVATE label() | PRIVATE label() | ||
Line 74: | Line 100: | ||
label(i%) = label | label(i%) = label | ||
= pass% | = pass% | ||
- | Here the macro takes as a parameter an ' | + | </ |
+ | |||
+ | Here the macro takes as a parameter an ' | ||
+ | |||
+ | <code bb4w> | ||
DIM code% 100, L% -1 | DIM code% 100, L% -1 | ||
FOR pass% = 8 TO 11 STEP 3 | FOR pass% = 8 TO 11 STEP 3 | ||
Line 87: | Line 117: | ||
NEXT pass% | NEXT pass% | ||
END | END | ||
- | As shown, the macro can be called up to ten times from the program (0 to 9); if this is insufficient the size of the **label()** array may be increased.\\ \\ If it's inconvenient to pass an ' | + | </ |
+ | |||
+ | As shown, the macro can be called up to ten times from the program (0 to 9); if this is insufficient the size of the **label()** array may be increased.\\ \\ If it's inconvenient to pass an ' | ||
+ | |||
+ | <code bb4w> | ||
DEF FNsimplisticabs | DEF FNsimplisticabs | ||
PRIVATE label(), p%, i% | PRIVATE label(), p%, i% | ||
Line 104: | Line 138: | ||
i% += 1 | i% += 1 | ||
= pass% | = pass% | ||
+ | </ | ||
+ | |||
**Note:** Although the interpreter accepts the direct use of array elements as assembler labels, which would allow the above code to be slightly simplified, this is not strictly valid syntax and is not permitted by the compiler. | **Note:** Although the interpreter accepts the direct use of array elements as assembler labels, which would allow the above code to be slightly simplified, this is not strictly valid syntax and is not permitted by the compiler. |
simulating_20assembler_20macros.1522502383.txt.gz · Last modified: 2024/01/05 00:16 (external edit)