Está en la página 1de 40

GUÍA DE REFERENCIA RÁPIDA A

mikroBasic
ESTIMADOS CLIENTES,
Querría darles las gracias por estar interesados en nuestros productos y por tener
confianza en MikroElektronika.
Nuestro objetivo es proporcionarles con los productos de la mejor calidad. Además,
seguimos mejorando nuestros rendimientos para responder a sus necesidades.

Nebojsa Matic
Director general
3

Visión general de los elementos léxicos


La guía referente proporciona definiciones formales de los elementos léxicos del lengua-
je de programación mikroBasic. Estos elementos son pareciados a las unidades recono-
cidas por mikroBasic. Cada programa escrito en mikroBasic consiste en las secuencias
de los caracteres ASCII tales como letras, dígitos y signos especiales. Los signos no
imprimibles (por ejemplo: carácter nueva línea, tabulador, etc) se refieren a los signos
especiales también. El conjunto de los elementos básicos en mikroBasic es organizado
y limitado. El programa se escribe en un editor de texto tal como mikroBasic Code Edi-
tor. Durante el proceso de compilación se realiza el análisis sintáctico (parsing). El pars-
er debe identificar los tokens de forma que el código fuente es tokenizado, es decir,
reducido a tokens y espacios en blanco (whitespace).

Espacio en blanco
El espacio en blanco (whitespace) es el nombre genérico dado a los espacios (en blanco),
tabuladores horizontales y verticales y nueva línea. Los espacios en blanco se utilizan
como separadores para indicar donde empiezan y terminan los tokens. Por ejemplo, las
dos secuencias:
dim tmp as byte
dim j as word

dim tmp as byte


dim j as word

son léxicamente equivalentes y el resultado del análisis son los ocho tokens siguientes
dim
tmp
as
byte
dim
j
as
word

Espacio en blanco en las cadenas literales


Cuando el espacio en blanco está dentro de una cadena literal no se utiliza como sepa-
rador, sino que se interpreta como un carácter común, esto es, como una parte de una
sola cadena. Por ejemplo, la siguiente cadena:
some_string = "mikro foo"

se descompone en cuatro tokens, con tal de que la cadena literal represente un token:
some_string
=
"mikro foo"
newline character
4

Tokens
El token es el elemento más pequeño del lenguaje de programación Basic reconocido
por el compilador. El código fuente es escaneado de izquierda a derecha. El analizador
sintáctico (parser) extrae los tokens, seleccionando el que coincida con la secuencia de
caracteres más larga posible dentro de la secuencia analizada.

Palabras clave
Las palabras clave o reservadas son los tokens que tienen el significado fijo y no se
pueden utilizar como identificadores. Aparte da las palabras clave estándar en
microBasic hay un conjunto de los identificadores predefinidos (de constantes y de vari-
ables) que describen el microcontrolador específico y no pueden ser redefinidos. Lista
alfabética de las palabras clave en Basic.
absolute cstr form let private stop
and curdir format line procedure str
appactivate currency forward loc program strcomp
array cvar freefile lock property strconv
as cverr function lof pset string
asc data fv long public structure
asm date get longint put sub
at dateadd getattr longword pv switch
atn datediff getobject loop qbcolor syd
attribute datepart gosub lset raise symbol
base dateserial goto me randomize system
bdata datevalue hex mid rate tab
beep ddb hour minute redim time
bit deftype idata mirr register timer
boolean dim if mkdir rem timeserial
byref dir iif mod resume timevalue
byte div ilevel module return to
call do imp month rgb typedef
case doevents implements msgbox right typename
cbool double include name rmdir ubound
cbyte each input new rnd ucase
ccur eio instr next rset unlock
cdate empty int not rx until
cdate end integer not sbit val
cdbl end with io nothing second variant
char environ ipmt now seek vartype
chdir eof irr nper select version
chdrive eqv is npv sendkeys volatile
chr erase isarray object set weekday
cint err isdate oct setattr wend
circle error isempty on sfr while
class exit iserror open sgn width
clear explicit ismissing option shell with
clng explicit isnull option short word
close fileattr isnumeric option single write
code fileattr isobject or sln xdata
command filecopy kill org small xor
compact filedatetime large orgall space
compare filelen lbound pdata spc
const fix lcase pmt sqr
createobject float left ppmt static
csng for len print step
5

Comentarios
Los comentarios son anotaciones utilizadas para interpretar el programa. Son para uso
exclusivo del programador. Se eliminan del código fuente antes del análisis sintáctico.
Los comentarios en mikroBasic deben ocupar sólo una línea. Para escribir comentarios
se utiliza el apóstrofo.
' Any text between an apostrophe and the end of the
' line constitutes a comment. May span one line only.

Además, los bloques de instrucciones en ensamblador pueden introducir los comentar-


ios unilíneas al colocar el signo ‘;’ delante del comentario.
asm
some_asm ; This assembly instruction …
end asm

Identificadores
Los identificadores son los nombres arbitrarios utilizados para identificar los objetos
básicos del lenguaje: etiquetas, tipos, símbolos, constantes, variables, procedimientos y
funciones. Los identificadores pueden contener todas las letras mayúsculas y minúscu-
las del abecedario (a a z, y A a Z), el guión bajo "_", y los dígitos 0 a 9. El primer carác-
ter debe ser una letra o el guión bajo. mikroBasic no distingue mayúsculas y minúscu-
las, así que Sum, sum y suM representan identificadores equivalentes. Aunque los nom-
bres de identificadores son arbitrarios (de acuerdo con las reglas fijas), ocurre un error
si se utiliza el mismo nombre para más de un identificador dentro del mismo ámbito.
Ejemplos de identificadores válidos:

temperatura_V1
Pritisak
no_hit
dat2string
SUM3
_vtext

y de identificadores inválidos:

7temp // NO -- no puede empezar por un numeral


%higher // NO -- no puede contener los caracteres especiales
xor // NO -- no puede coincidir con las palabras reservadas
j23.07.04 // NO -- no puede contener los caracteres especiales(dot)
6

Literales
Los literales son tokens que representan valores fijos y numéricos o valores de carac-
teres. El tipo de dato correspondiente a una constante es deducido por el compilador en
base a indicios implícitos, como el valor numérico y formato usados en el código fuente.

Constantes literales enteras


Las constantes literales enteras pueden estar expresadas en los formatos decimal, octal
o hexadecimal.

 En el formato decimal las constantes enteras se representan como una secuencia


de dígitos con el prefijo opcional + o - (no están delimitados por coma, espacio en
blanco o puntos). Si no se especifica el prefijo, el valor de la constante se considera
positivo. Por ejemplo, el número 6258 equivale a +6258.
 Las constantes con el prefijo ‘$’ o ‘0x’ se consideran números hexadecimales. Por
ejemplo, $8F o 0x8F
 Las constantes con el prefijo ‘%’ se consideran números binarios. Por ejemplo,
%01010101.
Ejemplos de las constantes literales:

11 ' literal decimal


$11 ' literal hexadecimal, equivale a literal decimal 17
0x11 ' literal hexadecimal, equivale a literal decimal 17
%11 ' literal binario, equivale a literal decimal 3

El rango permitido de los valores de constantes es determinado por el tipo longint para
las constantes con signo (signed) y por el tipo longword para las constantes sin signo
(unsigned).

Constantes literales de punto flotante (fraccionarias)


Las constantes literales de punto flotante consisten en:

 Parte entera;
 Punto decimal;
 Parte fraccionaria; y
 e/E y un entero con signo (exponente)

Ejemplos de las constantes de punto flotante:

0. // = 0.0
-1.23 // = -1.23
23.45e6 // = 23.45 * 10^6
2e-5 // = 2.0 * 10^-5
3E+10 // = 3.0 * 10^10
.09E34 // = 0.09 * 10^34
7

Literales carácter
Un literal carácter es una secuencia de caracteres ASCII delimitados por comillas sim-
ples. Un literal carácter puede ser asignado a variables de tipos entero y cadena, a una
matriz de caracteres y a una matriz de bytes. A una variable de tipo entero se le asig-
nará el valor ASCII del literal carácter correspondiente.
Cadenas literales (alfanuméricas)
Una cadena literal representa una secuencia de caracteres ASCII escritos en una línea
entre comillas dobles. Como hemos mencionado, una cadena literal puede contener
espacio en blanco, esto es, el parser no descompone las cadenas literales en tokens,
sino que las interpreta como una totalidad. La longitud de una cadana literal depende del
número de caracteres en los que consiste. Al final de cada cadena literal se añade un
carácter nulo (null), llamado el ASCII cero, que no cuenta en la longitud total de la cade-
na literal. Una cadena literal que no contiene ningún signo entre comillas (cadena nula)
se almacena como un solo carácter nulo. Las cadenas literales se pueden asignar a vari-
ables de tipo cadena, a una matriz de caracteres o a una matriz de bytes.
Ejemplos de cadenas literales:

"Hola mundo!" ' mensaje de 11 caracteres


"La temperatura es estable" ' mensaje de 25 caracteres
" " ' dos espacios de 2 caracteres
"C" ' letra C de 1 carácter
"" ' cadena nula de 0 caracteres

Puntuadores
Los puntuadores utilizados en mikroBasic (conocidos como separadores) son:
 [ ] - corchetes
 ( ) - paréntesis
 , - coma
 ; - punto y coma (sólo en las sentenias ASM)
 : - dos puntos
 . - punto

Corchetes
Los corchetes indican índices de matrices uni y multi dimensionales:
dim abecedario as byte [30]
' ...
abecedario [2] = "c"

Paréntesis
Los paréntesis ( ) sirven para agrupar expresiones, aislar expresiones condicionales,
indicar llamadas a funciones y declaraciones de éstas:

d = c * (a + b) ' modifica la precedencia normal


if (d = z) then ... ' expresión condicional
func() ' llamada a función, sin parámetros
sub function func2(dim n as word) ' declaración de función, con parámetros
8

Coma
La coma ‘,’ se utiliza para separar los parámetros en las llamadas a función, los identi-
ficadores en las declaraciones y los elementos del inicializador:
Lcd_Out(1, 1, txt)
dim i, j, k as word
const MESES as byte [12] = (31,28,31,30,31,30,31,31,30,31,30,31)

Punto y coma
El punto y coma indica el inicio de un comentario en los bloques en ensamblador.

Dos puntos
Dos puntos ‘:’ se utilizan para indicar una etiqueta en el programa:

start: nop
goto start

Punto
El punto ‘.’ se utiliza para acceder a un miembro de estructura y a los bits particulares
de registros. Por ejemplo:
nombre.apellido = "Smith"

Organización de programa
Como los demás lenguajes de programación, mikroBasic proporciona un conjunto de
reglas estrictamente definidas que se utilizan al escribir el programa. En otras palabras,
todos los programas escritos en mikroBasic tienen una estructura definida y organizada.
A continuación se muestran los ejemplos de escribir los ficheros de programa. Cada
proyecto en mikroBasic consiste en un fichero de proyecto y en uno o más módulos
(ficheros con extensión .mbas). El fichero de proyecto proporciona las informaciones del
proyecto, mientras que los módulos contienen el fuente de programa.

Módulo principal
Cada proyecto en mikroBasic requiere un solo módulo principal (main modul). Aquel módulo
se identifica por la palabra clave program que está al principio del módulo y da instucciones
al compilador de dónde debe iniciar el proceso de compilación. Después de crear un proyec-
to con éxito en Project Wizard, Code Editor visualizará automáticamente el módulo prin-
cipal. Code Editor contiene la estructura básica de un programa escrito en mikroBasic.
Aparte de comentarios, nada debe preceder a la palabra clave program. La cláusula
include se puede colocar después del nombre de programa. Todos los identificadores
globales (de constantes, variables, etiquetas, rutinas) se declaran delante de la palabra
clave main.
9

Organización del módulo principal


El módulo principal se puede dividir en dos partes: declaraciones y el cuerpo de progra-
ma. Las declaraciones deben estar organizadas y colocadas en el código apropiada-
mente. Al contrario, el compilador no puede interpretar el programa correctamente. Para
esribir el código es recomendable seguir el ejemplo a continuación.

programa <nombre_de_programa>
include <incluir_otros_módulos>

'********************************************************
'* Declaraciones globales:
'********************************************************

' declaraciones de símbolos


symbol ...

' declaraciones de constantes


const ...

' declaraciones de variables


dim ...

' deklaraciones de procedimientos


sub procedure procedure_name(...)
<declaraciones_locales>
...
end sub

' declariciones de funciones


sub function function_name(...)
<declaraciones_locales>
...
end sub
'********************************************************
'* Cuerpo de programa:
'********************************************************

main:
' escriba el código aquí
end.

Otros módulos
Otros módulos permiten:

 descomponer los programas largos en las partes encapsuladas que se pueden edi
tar por separado;
 crear librerías que se pueden utilizar en los proyectos diferentes; y
 distribuir librerías a otros programadores sin revelar el código fuente.
10

Cada módulo se almacena en su propio fichero y se compila por separado. Los módu-
los compilados se enlazan juntos con el propósito de crear un código ejecutable. Para
compilar un proyecto el compilador tiene que disponer de todos los módulos ya sean los
ficheros de código fuente o ficheros de objetos (ficheros creados por medio de la com-
pilación de módulos). Todos los módulos empiezan por la palabra clave modul. Aparte
de los comentarios nada debe preceder a la palabra clave modul. La cláusula include
se puede colocar después del nombre de módulo.
Organización de otros módulos
Cada módulo consiste en tres secciones: Include, Interface e Implementation. Sólo la
sección Implementation es obligatoria. Siga el modelo a continuación:

module <nombre_de_módulo>
include <incluir_otros_módulos>

'********************************************************
'* Interface (variables_globales):
'********************************************************

' declaraciones de símbolos


symbol ...

' declaraciones de constantes


const ...

' declaraciones de variables


dim ...
' prototipos de procedimientos
sub procedure procedure_name(...)

' prototipos de funciones


sub function function_name(...)
'********************************************************
'* Implementation:
'********************************************************
implements

' declaraciones de constantes


const ...
' declaraciones de variables
dim ...

' declaraciones de procedimientos


sub procedure procedure_name (...)
<declaraciones_locales>
...
end sub

' declaraciones de funciones


sub function function_name(...)
<declaraciones_locales>
...
end sub

end.
11

Cláusula Include
mikroBasic incluye los módulos por medio de la cláusula include. Consiste en la palabra
reservada include y el nombre de módulo entre comillas. El nombre del módulo no
incluye la extensión. Un módulo incluye varias cláusulas include que deben estar colo-
cadas inmediatamente después del nombre de módulo. Por ejemplo:

program MyProgram

include "utils"
include "strings"
include "MyUnit"
...

Después de llegar al nombre de módulo, el compilador comprueba si el proyecto con-


tiene ficheros con el nombre dado y las extensiones .mcl y .mbas, de acuerdo con el
orden y la ubicación especificados en la opción Search Paths.

 Si el compilador encuentra los dos ficheros con las extensiones .mbas y .mcl, comp
robará sus fechas e incluirá el fichero de la fecha más reciente en el proyecto. Si el
fichero de la extensión .mbas es de la fecha más reciente, el compilador lo recom
pilará y generará el nuevo fichero .mcl al copiar el antiguo;

 Si el compilador sólo encuentra el fichero de la extensión .mbas, el compilador lo


recompilará y generará el fichero de la extensión .mcl;

 Si encuentra el fichero de la extensión .mcl, el compilador lo incluirá en el formato dado;

 Si no encuentra ningún fichero, el compilador informa acerca del error

Sección Interface
La sección Interface es la sección del módulo que precede a la palabra clave imple-
ments. Esta sección contiene declaraciones globales (de constantes, variables y símbo-
los) para el proyecto dado. En ella no se pueden definir rutinas. Esta sección contiene
las declaraciones de rutinas (definidas en la sección Implementation) que deben ser
visibles fuera del módulo. Las declaraciones de rutinas deben corresponder completa-
mente a las definiciones de éstas.

Sección Implementation
Sección Implementation contiene las declaraciones y definiciones privadas de las ruti-
nas. Esta sección permite encapsular el código. Todo lo que se declara después de la
palabra clave implements es para el uso privado, es decir, el ámbito está limitado a
aquel módulo. Cualquier identificador declarado en esta sección del módulo no se puede
utilizar fuera del módulo, sino sólo en las rutinas definidas después de la declaración del
identificador dado.
12

Ámbito y visibilidad

Ámbito (scope)
El ámbito de un identificador representa la sección de programa en la que se puede uti-
lizar el identificador. Hay varias categorías del ámbito lo que depende de cómo y dónde
se declaran los identificadores:

Ubicación de declaración Ámbito


El identificador se declara en la El ámbito se extiende desde el punto
sección de declaración del módulo de declaración hasta el final del
principal, fuera de cualquier función o fichero, incluyendo todas las rutinas
procedimiento dentro del ámbito.
El identificador se declara en la El ámbito se extiende desde el punto
función o en el procedimiento de declaración hasta el final de la
rutina. Estos identificadores se
denominan locales.
El identificador se declara en la El ámbito se extiende desde el punto
sección Interface del módulo de declaración hasta el final del
módulo. Incluye otros módulos o
programas que utilizan ese módulo.
La única excepción son los símbolos
cuyo ámbito está limitado al fichero en
el que se declaran.
El identificador se declara en la El ámbito se extiende desde el punto
sección Implementation, pero no se de declaración hasta el final del
declara dentro de culaquier función o módulo. El identificador está
procedimiento disponible a cualquier función o
procedimiento definidos debajo de la
declaración del identificador.

Visibilidad
Similar al ámbito, la visibilidad representa la sección de programa en la que se puede
utilizar el identificador dado. Ámbito y visibilidad coinciden generalmente, si bien pueden
darse circunstancias en que un objeto puede aparecer invisible temporalmente debido a
la presencia de un identificador duplicado. El objeto existe, pero el identificador original
no puede ser utilizado para accederlo hasta que el identificador duplicado es terminado.
La visibilidad no puede exceder al ámbito, pero éste puede exceder a la visibilidad.
13

Tipos
mikroBasic es estrictamente un lenguaje de tipo, lo que significa que cada variable o
constante son de tipo definido antes de que se inicie el proceso de compilar. Al compro-
bar el tipo no es posible asignar o acceder incorrectamente a objetos.
mikroBasic soporta los tipos de datos estándar (predefinidos) tales como son los tipos
enteros con signo o sin signo de varios tamańos, matrices, cadenas, punteros etc.
Además, el usuario puede definir un nuevo tipo de datos al utilizar la directiva typedef.
Por ejemplo:

Typedef MyType1 as byte


Typedef MyType2 as integer
Typedef MyType3 as ^word
Typedef MyType4 as ^MyType1

dim mynumber as MyType2

Tipos simples
Los tipos simples son los tipos que no se pueden descomponer en los elementos más
básicos. En la tabla a continuación se muestran los tipos simples en mikroBasic:

Tipo Tamaño Rango


byte 8–bit 0 – 255
char* 8–bit 0 – 255
word 16–bit 0 – 65535
short 8–bit -128 – 127
integer 16–bit -32768 – 32767
longint 32–bit -2147483648 – 2147483647
longword 32-bit 0-4294967295
-38 38
float 32–bit ±1.17549435082 * 10 .. ±6.80564774407 * 10

* tipo char se puede interpretar como el tipo byte en todos los aspectos
14

Matrices
Una matriz representa un conjunto ordenado y limitado que contiene una serie de vari-
ables del mismo tipo, los elementos de la matriz. El tipo de elemento se denomina tipo
básico. Al valor de un elemento se le puede acceder por su índice que es único para
cada elemento, así que los elementos diferentes pueden contener el mismo valor.

Declaración de matrices
Las matrices se declaran de la siguiente manera:
element_type [array_lenght]

Cada elemento de una matriz está numerado de 0 a array_lenght -1. El especificador


element_type representa el tipo de elementos de matriz (tipo básico). A cada elemento
de matriz se le puede acceder al especificar el nombre de matriz seguido por el índice
de elementos entre corchetes. Por ejemplo:

dim weekdays as byte [7]


dim samples as word [50]

main:
' A los elementos de variables de matriz se les puede acceder de la sigu-
iente manera
samples [0] = 1
if samples [37] = 0 then
...

Matrices constantes
Una matriz constante se inicializa al asignarle una secuencia de valores delimitados por
comas entre paréntesis. Por ejemplo:

' Declarar una matriz constante que contiene el número de días en cada
mes:
const MONTHS as byte [12] = (31,28,31,30,31,30,31,31,30,31,30,31)
' Declaración de una matriz de constantes bidimensional:
const NUMBER s byte [4][4] = ((0, 1, 2, 3), (5, 6, 7, 8), (9, 10, 11, 12), (13, 14, 15, 16))

El número de los valores asignados no debe exceder a la longitud especificada de


matriz, pero puede ser menor. En este caso, a los demás elementos se les asignarán los
ceros hasta llegar a la longitud total.
15

Matrices multidimensionales
Una matriz es unidimensional si es de tipo escalar. A veces las matrices unidimension-
ales se denominan vectores. Las matrices multidimensionales se crean al declarar matri-
ces de tipo matriz.
El ejemplo de una matriz bidimensional:
dim m as byte [50][20] 'matriz bidimensional de tamańo 50x20

La variable m representa una matriz de 50 elementos. Cada uno representa una nueva
matriz de los elementos de tipo byte. Así se crea una matriz de 50x20 elementos. El
primer elemento es m[0][0], mientras que el último es m[49][19]. Si una matriz es un
parámetro de función, se pasa por su dirección como en el siguiente ejemplo:

sub procedure example(dim byref m as byte [50][20])


...
inc(m [1][1])
end sub
dim m as byte [50][20] 'matriz bidimensional de tamańo 50x20
dim n as byte [4][2][7] 'matriz tridimensional de tamańo 4x2x7
main:
...
func(m)
end.

Cadenas
Una cadena representa un conjunto de caracteres equivalente a una matriz de tipo char.
Se declara de la siguiente manera:

string [string_length]

El especificador string_name representa el nombre de la cadena y debe ser un identi-


ficador válido. El especificador string_length representa el número de caracteres en las
que consiste la cadena. Al final de cada cadena se añade un carácter nulo (null), llama-
do el ASCII cero, que no cuenta en la longitud total de la cadena. Una cadena nula ('')
representa una matriz que contiene sólo un caracter nulo.
Las cadenas se pueden asignar a las variables de tipo cadena, a la matriz de caracteres
y a la matriz de bytes.
Por ejemplo:
dim poruka1 as string [20]
dim poruka2 as string [19]
main:
msg1 = "Esto es el primer mensaje"
msg2 = "Esto es el segundo mensaje"
msg1 = msg2
16

A una cadena se le puede acceder elemento por elemento. Por ejemplo:

dim s as string [5]


...
s = "mik"
' s [0] es el literal de caracteres "m"
' s [1] es el literal de caracteres "i"
' s [2] es el literal de caracteres "k"
' s [3] es cero (carácter nulo)
' s [4] es indefinido
' s [5] es indefinido

Empalme de cadenas
mikroBasic permite empalmar las cadenas por medio del operador más (+). Este tipo de con-
catenación se puede aplicar a las variables de cadena, cadenas literales, variables cáracter y
literales carácter. Los caracteres no imprimidos se pueden representar por medio del operador
Chr y el número que es el código ASCII del carácter no imprimido correspondiente (Chr (13)
para CR). Por ejemplo:

dim mensaje as string [100]


dim res_txt as string [5]
dim res, channel as word
main:
res = Adc_Read(channel) ' Resultado de la conversión AD
WordToStr(res, res_txt) ' Crear una cadena del resultado númerico
' Preparar el mensaje de salida
mensaje = "Result is" + ' Texto "Resultado es"
Chr(13) + ' Ańadir la secuencia CR/LF
Chr(10) + ' Ańadir la secuencia LF
res_txt + ' Resultado de la conversión AD
"." ' Ańadir un punto

mikroBasic contiene la librería String que facilita operaciones con cadenas.


17

Punteros
Un puntero es una variable cuyo fin específico es almacenar direcciones de memoria de
objetos. Una variable accede directamente a la dirección de memoria mientras que el
puntero representa una referencia a la dirección. Para declarar un puntero, es necesario
ańadir el prefijo (^) delante del tipo. Por ejemplo, para declarar un puntero a un objeto
de tipo integer es necesario escribir:
^integer

Para acceder al dato almacenado en la locación de memoria a la que apunta un pun-


tero, es necesario ańadir el sufijo (^) al final del nombre de la variable. Por ejemplo,
vamos a declarar la variable p que apunta a un objeto de tipo word, y luego vamos a
asignarle al objeto el valor 5:

dim p as ^word
...
p^ = 5

Un puntero se puede asignar al otro puntero, después de que los dos apuntarán a la
misma locación de memoria. Al modificar el objeto al que apunta un puntero, será mod-
ificado automáticamente el objeto al que apunta otro puntero, porque se trata de la
misma locación de memoria.

Operador @
Operador @ devuelve la dirección de una variable o una rutina, es decir, dirige al pun-
tero a su operando. Las siguientes reglas se aplican al operador@:

 Si X es una variable, @X devuelve la dirección de X;

Si la variable X es de tipo array, el operador @ devolverá el puntero a su primer elemen-


to básico, excepto en el caso de que la parte izquierda de la expresión en la que se uti-
liza X sea el puntero a la matriz. En este caso, el operador @ devolverá el puntero a la
matriz, y no a su primer elemento básico.

typedef array_type as byte[10]

dim w as word
ptr_b as ^byte
ptr_arr as array_type
arr as byte[10]

main:
ptr_b = @arr ' @ operador devuelve ^byte
w = @arr ' @ operador devuelve ^byte
ptr_arr = @arr ' @ operador devuelve ^byte[10]
end.

 Si F es una rutina (función o un procedimiento), @F devuelve el puntero a F.


18

Puntero a función
mikroBasic permite el uso de los punteros a función. Este ejemplo muestra cómo definir y
utilizar un puntero a función. Primero vamos a definir el tipo procedural y el puntero a fun-
ción y por fin vamos llamar a función utilizando un puntero.

' Definición de tipo procedural


typedef TMyFunctionType = function (dim param1, param2 as byte, dim param3 as word) as word

dim MyPtr as ^TMyFunctionType ' Puntero al tipo procedural previamente definido


dim sample as word

' Definición de función


' Prototipo de función debe corresponder a la definición de tipo procedural
sub function Func1(dim p1, p2 as byte, dim p3 as word) as word '
result = p1 and p2 or p3 ' devuelve el valor
end sub

sub function Func2(dim abc, def as byte, dim ghi as word) as word
result = abc * def + ghi ' devuelve el valor
end sub

sub function Func3(dim first, yellow as byte, dim monday as word) as word '
result = monday - yellow - first ' devuelve el valor
end sub

' programa principal:


main:
' MyPtr ahora apunta a Func1
MyPtr = @Func1

' Llamar a función Func1 mediante puntero


Sample = MyPtr^(1, 2, 3)

' MyPtr ahora apunta a Func2


MyPtr = @Func2

' Llamar a función Func2 mediante puntero


Sample = MyPtr^(1, 2, 3)

' MyPtr ahora apunta a Func3


MyPtr = @Func3

' Llamar a función Func3 mediante puntero


Sample = MyPtr^(1, 2, 3)
end.
19

Estructuras
Las estructuras representan un conjunto heterogéneo de elementos. Cada elemento se
denomina el miembro. En la declaración de estructuras se especifica el nombre y el tipo
de cada miembro. La síntaxis de la estructura es la siguiente:
structure structname
dim member1 as type1
...
dim membern as typen
end structure

donde el especificador structname representa el nombre de estructura y debe ser el


identificador válido; los especificadores member1..membern representan uno o más
miembros de la estructura que deben ser identificadores válidos, mientras que los
especificadores type1.. typen representan los tipos de los miembros de estructura cor-
respondientes. El ámbito de un identificador de miembros está limitado a la estructura
en la que está, así que no hace falta tener en cuenta la coincidencia de los nombres de
los identificadores de miembros y las demás variables. En mikroBasic la estructura se
puede declarar sólo como un tipo nuevo. Por ejemplo, en la siguiente declaración es
creada la estructura denominada Dot:
structure Dot
dim x as float
dim y as float
end structure

Cada Dot contiene dos miembros: las coordenadas x y y. La memoria se asigna al


definir el objeto de tipo de estructura como en el siguiente ejemplo:
dim m, n as Dot

Mediante esta declaración son creados dos ejemplos de la estructura Dot, denominados m y
n. La estructura previamente definida puede ser el miembro de otra estructura Por ejemplo:
' Estructura que define un círculo:
structure Circle
dim radius as float
dim center as Dot
end structure

Acceso a miembros de estructura


A los miembros de estructura se les puede acceder mediante el operador punto ‘.’. Si
declaramos las variables circle1 y circle2 del tipo previamente definido Circle:
dim circle1, circle2 as Circle

a sus miembros individules se les puede acceder de la siguiente manera:

circle1.radius = 3.7
circle1.center.x = 0
circle1.center.y = 0
20

Conversión de tipos
La conversión de un objeto de un tipo definido es el proceso de cambiar su tipo en otro.
mikroBasic soporta las conversiones implícita y explícita de tipos básicos.

Conversión implícita
El compilador realizará la conversión implícita en los siguientes casos:

 si una sentencia requiere una expresión de tipo particular, y se utiliza la expresión


de tipo diferente;
 si un operador requiere un operando de tipo particular, y se utiliza un operando de tipo diferente;
 si una función requiere un parametro formal de tipo particular, y se le pasa el objeto de tipo diferente;
 si el resultado de una función no corresponde al tipo del valor devuelto.

Promoción
Cuando los operandos son de tipos diferentes, mediante la conversión implícita se real-
iza la promoción de tipo más bajo a tipo más alto, de la siguiente manera:

bit  byte/char
byte/char word
short  integer
short  longint
integer  longint
integral  float
word  longword

Los bytes más altos del operando sin signo extendido se llenan de ceros. Los bytes más
altos del operando con signo extendido se llenan del signo de bit. Si el número es nega-
tivo, los bytes más altos se llenan de ceros, al contrario se llenan de ceros. Por ejemplo:

dim a as byte
dim b as word
...
a = $FF
b = a ' promoción de a a word, de b a $00FF

Recorte
En las sentencias de asignación y en las sentencias que requieren una expresión de tipo
particular, el valor correcto será almacenado en el destino sólo si el resultado de expre-
sión no excede al rango del destino. Al contrario, si el resultado de la expresión excede
al rango del destino los bytes más altos se pierden.

dim i as byte
dim j as word
...
j = $FF0F
i = j ' i obtiene el valor $0F, byte más alto $FF se pierde
21

Conversión explícita
La conversión explícita se puede realizar en cualquier expresión al especificar el tipo
deseado (byte, word, short, integer, longint, longword o float) delante de la expre-
sión que será convertida. La expresión debe estar entre paréntesis. Un caso especial es
conversión entre los tipos con signo y sin signo. La conversión explícita de estos tipos
de datos no cambia la representación binaria de los datos. Por ejemplo:

dim a as byte
dim b as short
...
b = -1
a = byte(b) ' a is 255, not 1
' El dato se queda en la representación binaria 11111111
' pero el compilador la interpreta de la manera diferente

La conversión explícita no se puede realizar en el operando que está a la izquierda del oper-
ador de asignación:
word(b) = a Compilador informa acerca de un error

Ejemplo de la conversión:

dim a, b, c as byte
dim cc as word
...
a = 241
b = 128

c = a + b ' es igual a 113


c = word(a + b) ' es igual a 369
cc = a + b ' es igual a 369

Nota: Conversión de datos de punto flotante en datos integrales (en las sentencias de asignación
o mediante conversión explícita - typecasting) produce el resultado correcto sólo si el valor de
punto flotante no excede al ámbito de destino de tipo integral.
22

Variables
Las variables son los objetos cuyo valor se puede modificar en tiempo de ejecución. Cada
variable se declara bajo el nombre único que debe ser el identificador válido. Las variables
se pueden declarar en la sección de declaración de ficheros y rutinas. Cada varaible se
debe declarar antes de ser utilizada en el programa. Las variables globales (las que son vis-
ibles en todos los ficheros) se declaran en la sección de declaración del módulo principal.
Es necesario especificar el tipo de dato de cada variable. La síntaxis básica de la
declaración de variables es la siguiente:

dim identifier_list as type

El especificador identifier_list representa una lista de identificadores de variables sep-


arados por comas; el especificador type representa su tipo. mikroBasic permite utilizar
la versión reducida de la síntaxis que contiene sólo la palabra clave dim seguida por las
declaraciones de variables múltiples. Por ejemplo:

dim i, j, k as byte
counter, temp as word
samples as longint [100]

Constantes
Las constantes son los objetos cuyos valores se han definido en el momento de escribir
el código de programa, y no pueden ser modificados más tarde en tiempo de ejecución.
Las constantes no se almacenan en la memoria RAM. Las constantes se declaran en la
sección de declaración de ficheros y rutinas. La síntaxis es:
const constant_name [as type] = value

Cada constante se declara bajo el nombre único (especificador constant_name) que


debe ser el identificador válido. Los nombres de constantes se escriben normalmente en
mayúsculas. Al declarar una constante es necesario especificar su valor que corre-
sponde al tipo dado. No es obligatorio especificar el tipo. En ausencia de tipo el compi-
lador supone un tipo simple con el mínimo ámbito que corresponda al valor de con-
stante. MikroBasic permite utilizar una versión reducida de la síntaxis que contiene sólo
la palabra clave const seguida por las declaraciones de constantes múltiples. Por ejem-
plo:

const MAX as longint = 10000


MIN = 1000 ' compilador supone el tipo word
SWITCH = "n" ' compilador supone el tipo char
MSG = "Hello" ' compilador supone el tipo string
MONTHS as byte [12] = (31,28,31,30,31,30,31,31,30,31,30,31)
23

Etiquetas
Las etiquetas sirven como objetivos para las sentencias goto y gosub. Marque la sen-
tencia con la etiqueta como en el siguiente ejemplo:

label_identifier : statement

Las declaraciones de etiquetas no son obligatorias en mikroBasic. El nombre de la eti-


queta debe ser el identificador válido. La sentencia marcada así como las sentencias
goto/gosub deben pertenecer al mismo bloque. Por lo tento no es posible saltar a un
procedimiento o a una función o de ellos. Una etiqueta se puede declarar sólo una vez
dentro del mismo bloque.
Ejemplo del bucle infinito que llama al procedimiento Beep repetidamente:

loop: Beep
goto loop

Símbolos
Los símbolos en Basic permiten crear los macros simples sin parámetros. Cualquier
línea de código se puede reemplazar por un identificador. Los símbolos pueden aumen-
tar legibilidad y reutilización de código cuando se utilizan correctamente. Los símbolos
deben ser declarados al principio del módulo, bajo el nombre del módulo y la directiva
(opcional) include.

symbol alias = code

Los símbolos no se almacenan en la memoria RAM - el compilador reemplaza cada sím-


bolo por la línea de código apropiada de la declaración. Por ejemplo:

symbol MAXALLOWED = 216 'Símbolo como alias para el valor numérico


symbol PORT = PORTC 'Símbolo como alias para los SFR
symbol MYDELAY = Delay_ms(1000)'Símbolo como alias para llamar a procedimiento
dim cnt as byte 'Alguna variable
'...
main:
if cnt > MAXALLOWED then
cnt = 0
PORT.1 = 0
MYDELAY
end if
24

Funciones y procedimientos
Las funciones y los procedimientos, denominados bajo el nombre común rutinas, son
los subprogramas que ejecutan ciertas tareas a base de un número de los parámetros
de entrada. Las funciones devuelven el valor después de la ejecución, mientras que los
procedimientos no devuelven el valor. mikroBasic no soporta las rutinas inline.
Funciones
Las funciones se declaran de la siguiente manera:

sub function_name(parameter_list) as return_type


[declaraciones locales]
cuerpo de función
end sub

El especificador function_name representa el nombre de función y puede ser cualquier


identificador válido. El especificador parameter_list entre paréntesis es la lista de los
parámetros formales que se declaran de la manera similar a las variables. Para pasar
un parámetro a función por dirección se debe introducir la palabra clave byref al princi-
pio de la declaración del parámetro. Las declaraciones locales son las declaraciones
opcionales de variables, constantes y etiquetas y se refieren sólo a la función dada. El
cuerpo de función representa una secuencia de sentencias que se ejecutarán después
de llamar a función.
El especificador return_type representa el tipo de valor devuelto de función que puede
ser de tipo complejo. El ejemplo a continuación muestra cómo se define y utiliza función
que devuelve el tipo complejo.
structure TCircle ' Structure
dim CenterX, CenterY as word
dim Radius as byte
end structure

dim MyCircle as TCircle ' Global variable

' DefineCircle function returns a Structure


sub function DefineCircle(dim x, y as word, dim r as byte) as TCircle
result.CenterX = x
result.CenterY = y
result.Radius = r
end sub

main:
' Get a Structure via function call
MyCircle = DefineCircle(100, 200, 30)

' Access a Structure field via function call


MyCircle.CenterX = DefineCircle(100, 200, 30).CenterX + 20
' |------------------------| |------|
' | |
' Function returns TCircle Access to one field of TCircle
end.
25

Llamar a función
Una llamada a función se realiza al especificar su nombre seguido por los parámetros
actuales colocados en el mismo orden que los parámetros formales correspondientes.
El compilador es capaz de hacer los parámetros mal aparejados obtener el tipo adecua-
do de acuerdo con las reglas de la conversión implícita. Si hay una llamada a función en
la expresión, el valor devuleto de función se utilizará como el operando en dicha expre-
sión.
Esta función simple calcula xn a base de los parámetros de entrada x y n (n> 0):
sub function power(dim x, n as byte) as longint
dim i as byte
i = 0
result = 1
if n > 0 then
for i = 1 to n
result = result*x
next i
end if
end sub

Al llamar a esta función es posible calcular, por ejemplo, 312:

tmp = power(3, 12)

Procedimientos
Los procedimientos se declaran de la siguiente manera:

sub procedure procedure_name(parameter_list)


[declaraciones locales]
cuerpo de procedimiento
end sub

El especificador procedure_name representa el nombre de procedimiento y puede ser


cualquier identificador válido. El especificador parameter_list entre paréntesis repre-
senta la lista de parámetos formales que se declaran de la manera similar a las vari-
ables. Para pasar un parámetro a procedimiento por dirección se debe introducir la pal-
abra clave byref al principio de la declaración del parámetro. Las declaraciones locales
son las declaraciones opcionales de variables, constantes y etiquetas y se refieren sólo
al procedimiento dado. El cuerpo de procedimiento representa una secuencia de senten-
cias que se ejecutarán después de llamar a procedimiento.

Llamar a procedimiento
Una llamada a procedimiento se realiza al especificar su nombre seguido por los
parámetros actuales colocados en el mismo orden que los parámetros formales corre-
spondientes.
26

Operadores
Los operadores son un tipo de tokens que indican las operaciones que se realizan sobre
los operandos en una expresión. Si el orden de realización de operaciones no es deter-
minado explícitamente madiante paréntesis, lo determina el operador de precedencia.
Hay 4 categorías de precedencia en mikroBasic. Los operadores de la misma categoría
tienen igual precedencia. Cada categoría tiene reglas de asociatividad: de izquierda a
derecha () o de derecha a izquierda (). En ausencia de paréntesis, estas reglas
resuelven la agrupación de expresiones con operadores de igual presedencia.

Precedencia Operandos Operadores Asociatividad


4 1 @ not + - ←
3 2 * / div mod and << >> →
2 2 + - or xor →
1 2 = <> < > <= >= →

Operadores aritméticos
Los operadores aritméticos se utilizan para realizar operaciones matemáticas. Los operandos
de tipo char son los bytes, así que se pueden utilizar como los operandos sin signo en
operaciones aritméticas. Todos los operadores aritméticos se asocian de izquierda a
derecha.
Operador Operación Operandos Resultado
byte, short, byte, short,
suma integer, word, integer, word,
+ longint, dword, longint, dword, real
real
byte, short, byte, short,
- resta integer, word, integer, word,
longint, dword, longint, dword, real
real
byte, short, byte, integer, word,
* multiplicación integer, word, longint, dword,
dword, real short, real
división de los byte, short, byte, short,
/ objetos de punto integer, word, integer, word, real
flotante dword, real
división entera, byte, short, byte, short,
div redonde al entero integer, word, integer, word,
más cercano longint, dword longint, dword
módulo, devuelve el byte, short, byte, short,
resto de la división integer, longint, integer, longint,
mod de enteros (no word, dword word, dword
puede ser utilizado
con los objetos de
punto flotante)
27

División por cero


Al utilizar un cero (0) explícitamente como el divisor en la operación de división (x div 0),
es decir, al dividir cualquier número por cero, el compilador informa acerca de un error y
no genera el código. En caso de la división implícita, o sea en caso de que el divisor sea
un objeto cuyo valor es 0 (x div y, donde y=0), el resultado será indefinido.

Operadores aritméticos unitarios


El operador ‘-’ se utiliza como operador unitario para cambiar el signo de un objeto. El
operador + puede ser utilizado como operador aritmético unitario también, sin tener influ-
encia en el objeto. Por ejemplo:
b = -a

Operadores relacionales
Los operadores relacionales se utilizan para operaciones lógicas. Todos los operadores
relacionales devuelven CIERTO o FALSO. Realizan desplazamientos de izquierda a
derecha.

Operador Operación
= igual que
<> desigual que
> mayor que
< menor que
>= mayor o igual que
<= menor o igual que

Operadores relacionales en expresiones


La precedencia de los operadores aritméticos y relacionales permite que las expresiones
complejas generen el resultado esperado sin utilizar paréntesis. Por ejemplo:
a + 5 >= c - 1.0 / e '  (a + 5) >= (c - (1.0 / e))

Operadores de manejo de bits


Los operadores de manejo de bits se utilizan para modificar los bits individuales de
operandos. Los operadores de manejo de bits realizan desplazamientos de izquierda a
derecha. La única excepción es el complemento not que realiza un desplazamiento de
derecha a izquierda.
28

Tabla de los operadores de manejo de bits


Operador Operación
operador Y; compara pares de bits y devuleve 1 si los ambos bits
and están a 1; en caso contrario devuelve 0.
operador O; compara pares de bits y devuelve 1 si uno o los ambos
or bits están a 1; en caso contrario devuelve 0.
operador exclusivo O (XOR); compara pares de bits y devuelve 1 si
xor los ambos bits son complementarios; en caso contrario devuelve 0.
not operador de complemento (unitario); invierte cada bit
desplazamiento a izquierda; desplaza los bits a izquierda, el bit más
<< a la izquierda se pierde y se le asigna un 0 al bit más a la derecha.
desplazamiento a derecha; desplaza los bits a derecha, el bit más a
>> la derecha se pierde. Si el objeto carece de signo, se le asignará un
0 al bit más a la izquierda; en caso contrario se le asignará un signo
de bit.

Operadores lógicos de manejo de bits


Los operadores lógicos and, or o xor realizan operaciones sobre los pares de bits
apropiados de sus operandos. El operador not complementa a cada bit de un operan-
do. Por ejemplo:
$1234 and $5678 // es igual a $1230
{ because ..
$1234 : 0001 0010 0011 0100
$5678 : 0101 0110 0111 1000
----------------------------
and : 0001 0010 0011 0000 .. esto es, $1230 }

Operadores de desplazamiento de bits


Hay dos operadores de desplazamiento de bits en mikroBasic. Son el operador << que
realiza un desplazamiento de bits a la izquierda y el operador >> que realiza un
desplazamiento de bits a la derecha. Los operadores de desplazamiento de bits tienen
dos operandos. El operando izquierdo es un objeto que se desplaza, mientras que el
derecho indica el número de desplazamientos que se realizarán. Los dos operandos
deben ser de tipo integral. El operando derecho debe ser el valor positivo. Al desplazar
a la izquierda los bits que salen por la izquierda se pierden, mientras que los ‘nuevos’
bits a la derecha se rellenan con ceros. Por lo tanto, el desplazamiento del operando que
n
carace de signo a la izquierda por n posiciones equivale a multiplicarlo por 2 si todos
los bits descartados son ceros. Lo mismo se puede aplicar a los operandos con signo si
todos los bits descartados son iguales que el signo de bit. Al desplazar a la derecha los
bits que salen por la derecha se pierden, mientras que los ‘nuevos’ bits a la izquierda se
rellenan con ceros (en caso del operando sin signo) o con el signo de bit (en caso del
operando con signo). El desplazamiento del operando a la derecha por n posiciones
equivale a dividirlo por 2n.
29

Expresiones
Una expresión es una secuencia de operadores, operandos y puntuadores que devuel-
ven un valor. Las expresiones primarias son: literales, constantes, variables y llamadas
a función. Se pueden utilizar para crear las expresiones complejas por medio de oper-
adores. La forma de agrupación de los operandos y de las subexpresiones no represen-
ta obligatoriamente el orden en el que se evalúan en mikroBasic.

Sentencias
Las sentencias especifican y controlan el flujo de ejecución del programa. En ausencia
de las sentencias de salto y de selección, las sentencias se ejecutan en el orden de su
aparición en el código de programa.

Sentencias de asignación
Una sentencia de asignación se parece a lo siguiente:
variable = expression

La sentencia de asignación evalúa la expresión y le asigna el valor de la expresión a una


variable aplicando las reglas de la conversión implícita. El especificador variable puede
ser cualquier variable declarada, mientras que el especificador expression representa
la expresión cuyo valor corresponde a la variable dada. Hay que distinguir el operador
de asignación ‘=’ del operador relacional ‘=’ utilizado para comprobar igualdad.

Sentencias condicionales
Las sentencias condicionales o las sentencias de selección pueden decidir entre varios cur-
sos de acción distintos en función de ciertos valores.

Sentencia If
La sentencia If es una sentencia condicional. La síntaxis de la sentencia if es la siguiente:

if expression then
statement1
[else
statement2]
end if

Si expression se evalúa como cierto, statement1 se ejecuta. Si expression se evalúa


como falso, statement2 se ejecuta. La rama else compuesta de palabra clave else y la
sentencia statement2 es opcional.
30

Sentencia Select Case


La sentencia Select case es una sentencia condicional de ramificación múltiple. Con-
siste en una sentencia de control (selector) y una lista de los valores posibles de la
expresión. La síntaxis de la sentencia select case es la siguiente:

select case selector


case value_1
statement_1
...
case value_n
statement_n
[case else
default_statement]
end select

El especifiador selector es una expresión de control evaluada como un valor integral.


Los especifiadores value1..value_n representan los valores posibles del selector. Pue-
den ser literales, constantes o expresiones. Los especificadores statement1..state-
ment_n representan las sentencias. La cláusula else es opcional. Primero se evalúa el
valor de la expresión de control. Luego se compara con todos los valores disponibles. Si
coinciden los valores, se ejecutará la sentencia apropiada y terminará la sentencia
select case. En el caso de que coincidan los valores múltiples se ejecutará la primera
sentencia coincidente. Si no coincide ningún valor con el selector, se ejecutará la sen-
tencia default_statement en la rama else (si hay alguna).
Ejemplo de la sentencia select case:

select case operator


case "*"
res = n1 * n2
case "/"
res = n1 / n2
case "+"
res = n1 + n2
case "-"
res = n1 - n2
case else
res = 0
cnt = cnt + 1
end select

Los valores posibles de la expresión de control se pueden agrupar para que se varios
valores refierran a una sentencia. Es necesario enumerar los valores y separarlos por
comas.
31

select case reg


case 0
opmode = 0
case 1,2,3,4
opmode = 1
case 5,6,7
opmode = 2
end select

Sentencias Select Case anidadas


Las sentencias Select Case se pueden definir dentro de otras sentencias select case.
Este proceso es denominado anidamiento.

Sentencias de iteración
Las sentencias de iteración permiten repetir un conjunto de sentencias. Las sentencias
break y continue se pueden utilizar para controlar el flujo de ejecución de sentencias
de bucles. La sentencia break termina el bucle en el que está, mientras que la contin-
ue inicia la nueva iteración del bucle.

Sentencia For
La sentencia for se utiliza para implementación del bucle iterativo cuando el número de
iteraciones está especificado. La sintaxis de la sentencia for es la siguiente:

for counter = initial_value to final_value [step step_value]


statement
next counter

El especificador counter es una variable que se incrementa por el valor del paso
(step_value) con cada iteración del bucle. El parámetro step_value es un valor integral
opcional, que es igual a 1 por defecto si es omitido. Antes de ejecutar la primera iteración
el contador se pone al valor inicial (initial_value) y se incrementa hasta llegar (o exced-
er) al valor final (final_value). Con cada iteración se ejecuta la sentencia dada (state-
ment). Las expresiones initial_value y final_value deben ser compatibles con la vari-
able counter. El especificador statement puede ser cualquier sentencia que no cambia
el valor de la variable counter.
El parámetro step_value puede ser negativo, lo que permite contar atrás.
Ejemplo de calcular el producto escalar de dos vectores a y b, de la longitud n, utilizan-
do la sentencia for:

s = 0
for i = 0 to n-1
s = s + a [i] * b [i]
next i
32

Bucle infinito
La sentencia for resulta en un bucle infinito si final_value equivale o excede al rango de la vari-
able counter. Esto es un ejemplo del bucle infinito ya que la variable counter nunca alcanzará el
valor 300.
dim counter as byte
...
for counter = 0 to 300
nop
next counter
La otra forma de crear un bucle infinito en mikroBasic es por medio de la sentencia while.
Sentencia While
La sentencia while se utiliza para implementación del bucle iterativo cuando el número
de iteraciones no está especificado. Es necesario comprobar la condición de iteración
antes de la ejecución del bucle. La síntaxis de la sentencia while es la siguiente:
La sentencia statement se ejecuta repetidamente siempre que el valor de la expresión
while expression
statement
wend

expression sea cierto. El valor de la expresión se comprueba antes de que se ejecute la sigu-
iente iteración. Si el valor de la expresión es falso antes de entrar el bucle, no es ejecuta ningu-
na iteración, esto es, la sentencia statement no se ejecuta ninguna vez. La forma más sim-
ple de crear un bucle infinito es la siguiente:
while TRUE
...
wend

Sentencia Do
La sentenica do se utiliza para implementación del bucle iterativo cuando el número de
iteraciones no es especificado. La sentencia se ejecuta repetidamente hasta que la
expresión sea cierta. Es necesario chequear la condición de iteración al final del bucle.
La síntaxis de la sentencia do es la siguiente:
do
statement
loop until expression
La sentencia statement se ejecuta repetidamente hasta que el valor de la expresión
expression llegue a ser cierto. La expresión se evalúa después de cada iteración así
que la sentencia se ejecutará por lo menos una vez. Ejemplo de calcular el producto
escalar de dos vectores utilizando la sentencia do:

s = 0
i = 0
...
do
s = s + a [i] * b [i]
i = i + 1
loop until i = n
33

Sentencias de salto
mikroBasic soporta las siguientes sentenicas de salto: break, continue, exit, goto y
gosub.

Sentencia Break
A veces es necesario detener el bucle dentro del cuerpo. La sentencia break dentro del bucle
se utiliza para pasar el control a la primera sentencia después del bucle. Por ejemplo:

' Esperar a que se inserte la tarjeta CF ;


Lcd_Out(1, 1, "No card inserted")
while true
if Cf_Detect() = 1 then
break
end if
Delay_ms(1000)
wend

' tarjeta CF se puede utilizar ahora ...


Lcd_Out(1, 1, "Card detected")

Sentencia Continue
La sentencia continue dentro del bucle se utiliza para iniciar la nueva iteración del bucle.
Las sentencias que siguen después de la sentencia continue no se ejecutarán.

' continue salta aquí ' continue salta aquí do


for i = ... while condition ...
... ... continue
continue continue ...
... ... 'continue salta aquí
next i wend loop until condition

Sentencia Exit
La sentencia exit permite salir de rutina (función o procedimiento). Se pasa el control a
la primera sentencia después de la llamada a rutina. Ejemplo:

sub procedure Proc1()


dim error as byte
...
if error = TRUE then
exit
end if
... ' el código no se ejecutará si error tiene el valor TRUE
end sub
34

Sentencia Goto
La sentencia goto se utiliza para saltar de forma incondicional a la parte apropiada de
programa. La síntaxis de la sentencia goto es:

goto label_name

Por medio de esta sentencia se ejecuta el salto a la etiqueta label_name. No es posible


saltar a un procedimiento o una función o de ellos. La sentencia goto se puede utilizar
para salir de cualquier nivel de las estructuras anidadas. No es recomendable saltar a
bucles u otras sentencias estructuradas, ya que se pueden producir resultados inesepra-
dos. En general no es recomendable utilizar la sentencia goto dado que prácticamente
cada algoritmo se puede realizar sin ella dando programas estructurados legibles.
No obstante, la sentencia goto es útil para salir de las estructuras de control profunda-
mente anidadas.

for i = 0 to n
for j = 0 to m
...
if disaster
goto Error
end if
...
next j
next i
...
Error: ' error handling code

Sentencia Gosub
La sentencia gosub se utiliza para saltar de forma incondicional a la parte apropiada de
programa:
gosub label_name
...
label_name:
...
return

Por medio de esta sentencia es posible saltar a la etiqueta label_name. Cuando aparece
la sentencia return el programa sigue ejecutando con la siguiente sentencia después de la
sentencia gosub. Esta sentencia puede preceder o seguir la declaración de etiqueta.
35

Sentencia asm
mikroBasic permite embeber las instrucciones en ensamblador en el código de progra-
ma por medio de las sentencias asm. Las instrucciones en ensamblador se pueden
agrupar utilzando la palabra clave asm:

asm
bloque de instrucciones en ensamblador
end asm

mikroBasic permite escribir los comentarios en el código ensamblador embebido.


Además, los comentarios unilíneas en ensamblador se pueden escribir al introducir
punto y coma ‘;’ delante del comentario.

program test
dim myvar as word
main:
myvar = 0
asm
MOVLW 10
MOVWF _myvar
end asm
end.
36

Directivas
Las directivas son las palabras de significado especial que proporcionan las prosibili-
dades adicionales al compilar y mostrar los resultados.

Directivas de compilador
mikroBasic trata los comentaros que empiezan por el signo ‘#’ como directivas de com-
pilador. Estas directivas, entre otras cosas, permiten compilar el código de programa
condicionalmente, es decir, seleccionar las secciones particulares del código para com-
pilarlas. Todas las directivas de compilador deben ser terminadas en el fichero en el que
han empezado.

Directivas #DEFINE y #UNDEFINE


La directiva #DEFINE se utiliza para definir una constante condicional de compilador -
una bandera (flag). La bandera puede ser cualquier identificador válido. Las banderas
tienen los espacios de nombres separados así que no hay posibilidad de confusión con
los identificadores de programa. Es posible definir sólo una bandera por directiva. Por
ejemplo:
#DEFINE extended_format

La diretiva #UNDEFINE sirve para indefinir (borrar) la bandera previamente definida.

Directivas #IFDEF..#ELSE
La compilación condicional se realiza por medio de la directiva #IFDEF. Esta directiva
comprueba si una bandera está actualmente definida o no (utilizando la directiva
#DEFINE). La directiva #IFDEF termina por la directiva #ENDIF y puede contener una
cláusula #ELSE opcional:

#IFDEF flag
block of code
#ENDIF
#IFDEF flag_n
block of code n ]
[ #ELSE
alternate block of code ]
#ENDIF

Primero directiva #IFDEF comprueba si la bandera está definida por la directiva


#DEFINE. Si está definida, se compilará sólo <block of code>. Si no está definida, se
compilará <alternate block of code>. La directiva #ENDIF seńala el final de la secuen-
cia de compilación condicional. El resultado de lo anteriormente dicho es que sólo una
sección de código (puede estar vacía) será compilada. La parte compilada puede con-
tener las directivas condicionales adicionales (anidadas). Cada directiva #IFDEF debe
terminar por la directiva #ENDIF. Por ejemplo:
37

' Descomentar la bandera apropiada:


'#DEFINE resolution8
#IFDEF resolution8 THEN
... ' code specific to 8-bit resolution
#ELSE
... ' default code
#ENDIF

Banderas previamente definidas


mikroBasic dispone de las banderas previamente definidas que se pueden utilizar para
compilar el código de programa para los diferentes plataformas de hardware.

Directivas de enlazamiento
mikroBasic utiliza el algoritmo interno para distribuir los objetos dentro de memoria. Si
es necesario tener una variable o una rutina en una dirección predefinida y específica,
se utilizan las directivas de enlazamiento absolute, org y orgall.

Directiva absolute
Direktiva absolute especifica la dirección inical de una variable en ls memoria RAM. Si
una variable es multi-byte, los bytes altos se almacenarán en las locaciones consecuti-
vas adyacentes empezando por la locación dada. Esta directiva se ańade a la
declaración de la variable:

dim x as byte absolute $22


' Variable x ocupa 1 byte en la dirección $22

dim y as word absolute $23


' Varibale y ocupa 2 bytes en las direcciones $23 y $24

Directiva org
Directiva org especifica la dirección inicial de una rutina en memoria ROM. Se ańade a
la declaración de rutina. Por ejemplo:

sub procedure proc(dim par as byte) org $200


' Procedimiento proc se almacenará en la dirección $200
...
end sub

A los agregados constantes (estructuras, matrices) se les puede asignar espacio en una
dirección especificada en memoria ROM por medio de directiva org.

const arr as byte[10] = (0,1,2,3,4,5,6,7,8,9) org 0x400


' matriz constante ocupa 10 bytes en la dirección 0x400
38

La excepción son los procedimientos interrupt a los que no se puede asignar espacio en
la dirección especificada en memoria ROM por medio de esta directiva.

Directiva orgall
La directiva orgall especifica la dirección inicial de una rutina en memoria ROM desde
la que empieza colocación de todas las rutinas y constantes. Por ejemplo:

main:
orgall(0x200) ' Todas las rutinas y constantes en el programa serán
almacenadas encima de la dirección 0x200, incluyéndola también.
...

end.
TÉRMINOS Y CONDICIONES

Todos los productos de MikroElektronika son protegidos por la ley y por los tratados
internacionales de derechos de autor. Este manual es protegido por los tratados de
derechos de autor, también. Es prohibido copiar este manual, en parte o en conjunto sin
la autorización previa por escrito de MikroElektronika. Se permite imprimir este manual
en el formato PDF para el uso privado. La distribución y la modificación de su contenido
son prohibidas.

MikroElektronika proporciona este manual “como está” sin garantías de ninguna


especie, sean expresas o implícitas, incluyendo las garantías o condiciones implícitas de
comerciabilidad y aptitud para fines específicos.

Aunque MikroElektronika ha puesto el máximo empeńo en asegurar la exactitud de la


información incluida en este manual, no asume la responsabilidad de ninguna especie
de dańos derivados del acceso a la información o de los programas y productos
presentados en este manual (incluyendo dańos por la pérdida de los beneficios
empresariales, información comercial, interrupción de negocio o cualquier otra pérdida
pecuniaria).Las informaciones contenidas en este manual son para el uso interno.
Pueden ser modificadas en cualquier momento y sin aviso previo.

ACTIVIDADES DE ALTO RIESGO

Los productos de MikroElektronika no son tolerantes a fallos y no están diseńados,


fabricados o pensados para su uso o reventa como equipo de control en línea en entornos
peligrosos que requieran un funcionamiento sin fallos, como en instalaciones nucleares, en
la navegación aérea o en sistemas de comunicaciones, de tráfico aéreo, máquinas de
auxilio vital o sistemas de armamento, en los que un fallo del software podría conducir
directamente a la muerte, lesiones corporales o dańos físicos o medioambientales graves
(“Actividades de alto riesgo”). MikroElektronika y sus proveedores niegan específicamente
cualquier garantía expresa o implícita de aptitud para Actividades de alto riesgo.

MARCAS REGISTRADAS

Los productos y los nombres corporativos utilizados en este manual son protegidos por
la ley de los derechos de autor, sin reparar en la ausencia de notas adicionales. Las
marcas registradas son utilizadas exlusivamente con el propósito de identificar y explicar
los conceptos correspondientes y en beneficio de sus respectivos propietarios, sin
intención de infringirlas.

Copyright© 2003 – 2009 por MikroElektronika. Todos los derechos reservados.


Si quiere saber más de nuestros productos, por favor visite nuestra página web www.mikroe.com
Si tiene problemas con cualquiera de nuestros productos o sólo necesita información adicional, deje
un ticket en www.mikroe.com/en/support
Si tiene alguna pregunta, comentario o propuesta de negocio, póngase en contacto con nosotros en
office@mikroe.com

También podría gustarte