95 of 158
89 Chapter 4 – Special Considerations for Native Mode Devices With the native mode devices like the ZX-24n, the ZBasic compiler produces native object code that is executed by the microcontroller. This is in contrast to the VM mode devices where the ZBasic compiler produces instructions that are executed by the ZX virtual machine running on the underlying microcontroller. Because the native mode code runs directly on the underlying microcontroller instead of the more controlled virtual machine environment, there are several additional features that you can employ in your application. Moreover, there are several additional issues of which you must be aware as you write the code for your application or when you port your code from a VM mode device to a native mode device. 4.1 Using Inline C and Assembly Code When compiling ZBasic code for a native mode device, the compiler first produces equivalent C code corresponding to the subroutines, functions and data definitions of each module. Then, the resulting code is compiled into native object code for the underlying processor and linked with the ZX Runtime Library to produce an executable file that can be downloaded into the target device. In some cases it may be useful or desirable to inject sequences of C or native assembly language code directly into the code stream that is produced by the ZBasic compiler. The mechanism provided for doing this is similar for the two cases – the code lines to be injected are bracketed by lines containing the special directives #c and #endc or #asm and #endasm. All of the text lines between the beginning marker and the end marker, but excluding those marker lines, are copied verbatim to the output file corresponding to the module being compiled. It is important to note that no syntax checking or other analysis is performed on the code that is copied so you must be sure that the code is syntactically and semantically correct. Inline code sequences that occur outside of any subroutine or function are included in the module’s output file after the module’s data definitions but before any of the generated subroutine/function definitions. Inline code sequences that occur inside of a subroutine or function are placed in the generated code at the corresponding position for the routines to which they belong. Consider this simple example using inline C code: Dim b as Byte #c char ch; #endc Sub Main() b = 5 #c ch = zv_b; #endc End Sub Note, particularly, that ZBasic variable names are prefixed by zv_ in the generated C code. This is done to avoid namespace conflicts that might occur if the ZBasic variable names were used in the generated C code without a prefix. Other elements of the ZBasic program have distinguishing prefixes as well, as shown in the table below. Accessing ZBasic program elements using the prefixed names in inline C code is fairly straightforward. However, you must keep in mind that the ZBasic compiler may eliminate some variables that you define in your program if they are not used or if the ZBasic compiler’s optimizer determines that they aren’t needed. If you want to ensure that the ZBasic compiler will not eliminated a variable you’ve defined you can define it with the Volatile attribute. That attribute is a signal to the ZBasic compiler to not make any assumptions about the value of the variable at any given point in time.