Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Miky Gonzalez

#31
Programación C/C++ / [C] Kernel - Contru...ctor
9 Octubre 2013, 19:26 PM
¡ADVERTENCIA!: Este tema contiene datos de otras páginas. Existe código ensamblador en el código.

Primero de todo, deberían revisar como funciona el ordenador para poder entender la práctica que aquí les pongo. No lo voy a explicar, hay muchos sitios donde se explica el funcionamiento interno de un ordenador.

El código fuente de mi Kernel se divide en varios archivos, para mantener el código ensamblador necesario apartado del código C. Empezaré por el primer archivo que debo crear:

Código (asm) [Seleccionar]
.section multiboot
// Cabezera multiboot
.align 4
.int 0x1badb002
.int 0x0
.int -0x1badb002

.section .text

// "init" es una función definida en init.c
.extern init

// _start debe ser global, para que el enlazador pueda encontrarla y
// usarla como punto de entrada.
.global _start
_start:
   // Inicializar la pila
   mov $kernel_stack, %esp

   // Llamar al código C
   call init

   // Parar CPU - retorno desde código C
   hlt

.section .bss
.space 8192
kernel_stack:


El próximo archivo que deberiamos crear sería el código C (init.c):

void init(void) {
   while(1) ;
}


Por último necesitamos un enlazador que nos permita enlazar correctamente el código C y el código ensamblador para poder usarlo en nuestro bootloader (yo usaré GRUB2):

Código (asm) [Seleccionar]
/*  En _start debe iniciar la ejecución */
ENTRY(_start)
SECTIONS {
   . = 0x100000;
   .text : {
       *(multiboot)
       *(.text)
   }
   .data ALIGN(4096) : {
       *(.data)
   }
   .rodata ALIGN(4096) : {
       *(.rodata)
   }
   .bss ALIGN(4096) : {
       *(.bss)
   }
}


Hasta ahora, compilando nuestro código y virtualizándolo (por ejemplo yo uso QEMU), nos saldrá la pantalla de como GRUB carga nuestro Kernel, pero... ¿cómo sabemos que lo cargo?.
La dirección de memoria de video (estándar - sin paginación) es la dirección 0x8B000. Sabiendo esto y que hay 25 columnas por 80 filas, y que se necesita un valor de color letra, podemos escribir un "Hola mundo" en pantalla:

char *video = (char *) 0xB8000; // Dirección memoria video
unsigned short int x = 0, y = 0; // Actual posición puntero

void putchar(char chr) {
   if((chr == '\n') || (x > 79)) {
       x = 0;
       y++;
   }
   if(chr == '\n')
       return;

   if(y > 24) {
       int i;
       for (i = 0; i < 2 * 24 * 80; i++)
           video[i] = video[i + 160];

       for (; i < 2 * 25 * 80; i++)
           video[i] = 0;
       y--;
   }

   video[2 * (y * 80 + x)] = chr;
   video[2 * (y * 80 + x) + 1] = 0x07; // Color "default"

   x++;
   return;
}


Con esto, desde nuestro código init, podríamos hacer:

int bucle_i;
char *str1 = "Hola Mundo!"; // 11 carácteres

for(bucle_i = 0; bucle_i < 11; bucle_i++)
   putchar(str1[bucle_i]);


Esto sería nuestra gran primitiva función printf de C. Podríamos crear una función strlen y usar de esta forma:
void printf(char *str) {
   int bucle_i = 0;

   for(; bucle_i < strlen(str); bucle_i++)
       putchar(str[bucle_i]);
}


Eso es todo, intentaré publicar avances y código de mi kernel.

[FUENTES]
#32
Programación C/C++ / Re: Numeros primos
2 Octubre 2013, 20:20 PM
Me hizo gracia el código de eferion  ;D, seguro que yo cobraria más barato que el y admito muchas formas de pago (paypal, bitcoins...)... Ya en serio, fuera bromas, puedes utilizar el método de la cripta de erastóstenes (hay métodos muchos más rápidos) pero si no te especifican nada, prueba a implementarlo:

http://es.wikipedia.org/wiki/Criba_de_Erat%C3%B3stenes
#33
Totalmente de acuerdo con todos ustedes, si continuo el proyecto, intentaré implementar lo mejor posible para optimizar en velocidad.
  Saludos
#34
En primer lugar, gracias por comentar eferion. Soy consciente que con más instrucciones y más funciones el código será "sucio" y poco optimizable, pero para empezar, me parece que está claro.

Decidí programar la máquina virtual en C, porque no soy amigo de C++, aunque la programación orientada a objetos sería una buena idea, incluso tal vez mas editable.

En cambiar el switch por un array, o una estructura ya lo pensé, pero decidí no implementarlo por no tener que cambiar el código, aunque en implementarlo no se tardaría mucho, tan solo sería separar cada instrucción como una función del programa. Sería un paso a hacer si se continuara el proyecto añadiendo más instrucciones y funciones.

Estuve buscando cómo implementar y hacer funciones más rápidas y de hecho tengo una versión que podría proporcionar perfectamente libre de licencia, pero con un código mal organizado y poco ordenado, pero está bastante más optimizado comparandolo con este código.

Otro de los pasos a hacer si continuara el proyecto sería terminar el ensamblador, publicar la versión con uso de memoria y punteros en vez de una pila de datos; entre otras cosas, añadir 'labeles' para hacer saltos relativos en el código, de este manera, el problema actual de tener que cambiar de salto por cada nueva instrucción añadida se solventaría, convirtiendo los saltos relativos a saltos absolutos (esto lo haría el ensamblador).

Saludos,
  Miky Gonzalez
#35
Adjunto el código fuente de una máquina simple que he estado haciendo, pero no tengo más tiempo para continuarla ni tampoco para terminar el ensamblador. Actualmente dispone de las siguientes funciones:




Set de instrucciones:
0x00haltdetiene el cpu
0x01litcargar en acumulador un valor inmediato
0x02loadcargar en acumulador valor de un registro
0x03storealmacenar valor acumulador en un registro
0x04incincrementar por 1 el acumulador
0x05decdecrementar por 1 el acumulador
0x06putlponer en memoria un valor inmediato
0x07putrponer en registro un valor de memoria
0x08getacargar en acumulador un valor de memoria
0x09getrcargar en registro un valor de memoria
0x0Acmplcomparar acumulador con valor inmediado. establece flag
0x0Bcmprcomparar acumulador con valor registro. establece flag
0x0Cjmpsaltar a direccion de codigo (inicio == 0x00)
0x0Djmplsaltar a direccion de codigo si flag == 1 ( < )
0x0Ejmpesaltar a direccion de codigo si flag == 2 ( = )
0x0Fjmpg    saltar a direccion de codigo si flag == 3 ( > )



Especificaciones técnicas:
El CPU consta de 4 registros de usuario, un registro flag y el registro acumulador. La máquina dispone de memoria a modo de pila (tengo otra versión con memoria dinámica, en vez de usar una pila); también se dispone de una memoria de sólo lectura para el código.




main.c:
/*!
Miky Gonzalez Virtual Machine
Contact: mikygonzalez95@gmail.com

Miky Gonzalez Virtual Machine por Miky Gonzalez se encuentra bajo una
Licencia Creative Commons Atribución-NoComercial-CompartirIgual 3.0
Unported. Más información:
http://creativecommons.org/licenses/by-nc-sa/3.0/deed.es
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//#include <inttypes.h>
//#include <time.h>

#include "pila.h"

/* MVM - Estructura de la MV */
typedef struct CPU {
short int registro[4];
short int acumulador;
unsigned int inst_pointer;
unsigned char *memoria_codigo;
unsigned char flag;
pila_ pila;
} cpu_t;

unsigned int crear_cpu(cpu_t *cpu, unsigned char *memoria_codigo) {
if(!memoria_codigo || !cpu) return 0;

//memset(cpu->registro, 0, sizeof(cpu->registro) / sizeof(*cpu->registro));
unsigned short int i = 0;
for(; i < 4; i++)
cpu->registro[i] = 0;
cpu->acumulador = 0;
cpu->inst_pointer = 0;
cpu->memoria_codigo = memoria_codigo;
cpu->flag = 0;
cpu->pila = NULL;

return 1;
}

void ejecutar_cpu(cpu_t *cpu) {
if(!cpu) {
printf("[MVM] Error al ejecutar CPU...\n");
return;
}
while(1) {
switch(cpu->memoria_codigo[cpu->inst_pointer]) {
case 0x00: /*! halt */
printf("halt\n");
return;
case 0x01: /*! lit */
cpu->acumulador = cpu->memoria_codigo[++cpu->inst_pointer];
printf("lit %d\n", cpu->memoria_codigo[cpu->inst_pointer]);
break;
case 0x02: /*! load */
if(cpu->memoria_codigo[++cpu->inst_pointer] > 0x03) {
printf("[CPU] Desbordamiento en numero de registro.\n");
return;
}
cpu->acumulador = cpu->registro[cpu->memoria_codigo[cpu->inst_pointer]];
printf("load r%d\n", cpu->memoria_codigo[cpu->inst_pointer]);
break;
case 0x03: /*! store */
if(cpu->memoria_codigo[++cpu->inst_pointer] > 0x03) {
printf("[CPU] Desbordamiento en numero de registro.\n");
return;
}
cpu->registro[cpu->memoria_codigo[cpu->inst_pointer]] = cpu->acumulador;
printf("store r%d\n", cpu->memoria_codigo[cpu->inst_pointer]);
break;
case 0x04: /*! inc */
cpu->acumulador++;
printf("inc\n");
break;
case 0x05: /*! dec */
cpu->acumulador--;
printf("dec\n");
break;
case 0x06: /*! pushl */
push(&cpu->pila, cpu->memoria_codigo[++cpu->inst_pointer]);
printf("pushl %d\n", cpu->memoria_codigo[cpu->inst_pointer]);
break;
case 0x07: /*! pushr */
if(cpu->memoria_codigo[++cpu->inst_pointer] > 0x03) {
printf("[CPU] Desbordamiento en numero de registro.\n");
return;
}
push(&cpu->pila, cpu->registro[cpu->memoria_codigo[cpu->inst_pointer]]);
printf("pushr r%d\n", cpu->memoria_codigo[cpu->inst_pointer]);
break;
case 0x08: /*! pop */
if(pila_vacia(&cpu->pila)) {
printf("[CPUSTACK] No hay elemento en pila.\n");
return;
}
pop(&cpu->pila);
printf("pop\n");
break;
case 0x09: /*! loadt */
if(pila_vacia(&cpu->pila)) {
printf("[CPUSTACK] No hay elemento en pila.\n");
return;
}
cpu->acumulador = pop(&cpu->pila);
printf("loadt\n");
break;
case 0x0A: /*! cmpl */
if(cpu->acumulador < cpu->memoria_codigo[++cpu->inst_pointer])
cpu->flag = 1;
else if(cpu->acumulador == cpu->memoria_codigo[cpu->inst_pointer])
cpu->flag = 2;
else if(cpu->acumulador > cpu->memoria_codigo[cpu->inst_pointer])
cpu->flag = 3;
printf("cmpl %d\n", cpu->memoria_codigo[cpu->inst_pointer]);
break;
case 0x0B: /*! cmpr */
if(cpu->acumulador < cpu->registro[cpu->memoria_codigo[++cpu->inst_pointer]])
cpu->flag = 1;
else if(cpu->acumulador == cpu->registro[cpu->memoria_codigo[cpu->inst_pointer]])
cpu->flag = 2;
else if(cpu->acumulador > cpu->registro[cpu->memoria_codigo[cpu->inst_pointer]])
cpu->flag = 3;
printf("cmpr r%d\n", cpu->memoria_codigo[cpu->inst_pointer]);
break;
case 0x0C: /*! jmp */
printf("jmp %d\n", cpu->memoria_codigo[++cpu->inst_pointer]);
cpu->inst_pointer = cpu->memoria_codigo[cpu->inst_pointer] - 1;
break;
case 0x0D: /*! jmpl */
printf("jmpl %d\n", cpu->memoria_codigo[++cpu->inst_pointer]);
if(cpu->flag == 1)
cpu->inst_pointer = cpu->memoria_codigo[cpu->inst_pointer] - 1;
break;
case 0x0E: /*! jmpe */
printf("jmpe %d\n", cpu->memoria_codigo[++cpu->inst_pointer]);
if(cpu->flag == 2)
cpu->inst_pointer = cpu->memoria_codigo[cpu->inst_pointer] - 1;
break;
case 0x0F: /*! jmpg */
printf("jmpg %d\n", cpu->memoria_codigo[++cpu->inst_pointer]);
if(cpu->flag == 3)
cpu->inst_pointer = cpu->memoria_codigo[cpu->inst_pointer] - 1;
break;
default:
printf("[CPU] Instruccion desconocida. Cerrando proceso CPU.\n");
return;
}
cpu->inst_pointer++;
printf("r0: %d\tr1: %d\tr2: %d\tr3: %d\tac: %d\n", cpu->registro[0], cpu->registro[1], cpu->registro[2], cpu->registro[3], cpu->acumulador);
contar_nodos(cpu->pila);
}
}

int main(int argc, char *argv[]) {
/* Inicializar datos y comprobar argumentos */
if(argc < 2) {
printf("Uso: %s <archivo>\n", argv[0]);
return 0;
}
FILE *codigo_archivo = fopen(argv[1], "rb");
if(!codigo_archivo) {
printf("[MVM] Fallo al abrir el archivo %s\n", argv[1]);
return 0;
}

/* Calcular tamaño (volumen) del código */
unsigned int codigo_volumen;
fseek(codigo_archivo, 0, SEEK_END);
codigo_volumen = ftell(codigo_archivo);
rewind(codigo_archivo);
if(!codigo_volumen) {
printf("[MVM] No hay instrucciones...\n");
fclose(codigo_archivo);
return 0;
}

/* Reservar el espacio necesario para almacenar
* el código en memoria. Si existe, copiarlo. */
unsigned char *codigo = (unsigned char *)malloc(codigo_volumen);
if(!fread(codigo, 1, codigo_volumen, codigo_archivo)) {
printf("[MVM] Error en lectura de archivo...\n");
fclose(codigo_archivo);
return 0;
} else fclose(codigo_archivo);

/* Crear CPU e inicializar los datos */
cpu_t cpu;
if(!crear_cpu(&cpu, codigo)) {
printf("[MVM] Error al crear CPU...\n");
return 0;
}

/* Ejecutar CPU hasta instrucción fin o error */
ejecutar_cpu(&cpu);
printf("r0: %d\tr1: %d\tr2: %d\tr3: %d\tac: %d\n", cpu.registro[0], cpu.registro[1], cpu.registro[2], cpu.registro[3], cpu.acumulador);
contar_nodos(cpu.pila);
eliminar_pila(&cpu.pila);
free(codigo);

getchar();
return 0;
}


pila.c:
/*!
Miky Gonzalez Virtual Machine
Contact: mikygonzalez95@gmail.com

Miky Gonzalez Virtual Machine por Miky Gonzalez se encuentra bajo una
Licencia Creative Commons Atribución-NoComercial-CompartirIgual 3.0
Unported. Más información:
http://creativecommons.org/licenses/by-nc-sa/3.0/deed.es
*/

/*! Implementación de una pila para memoria de datos MVM */

#include <stdio.h>
#include <stdlib.h>
#include "pila.h"

void push(pila_ *pila, int valor) {
nodo_ nodo = (nodo_)malloc(sizeof(nodo_t));

if(nodo != NULL) {
nodo->valor = valor;
nodo->nodo_siguiente = *pila;
*pila = nodo;
}
}

int pop(pila_ *pila) {
nodo_ nodo;
int valor = 0;

nodo = *pila;
valor = (*pila)->valor;
*pila = (*pila)->nodo_siguiente;

free(nodo);
return valor;
}

//#define pila_vacia(a) *a == NULL ? 1:0;
unsigned short int pila_vacia(pila_ *pila) {
return (*pila == NULL ? 1 : 0);
}

unsigned short int contar_nodos(nodo_ nodo) {
if(nodo == NULL) return 0;

unsigned short int nodos = 0;
while(nodo != NULL) {
nodos++;
printf("n%d: %d\t", nodos, nodo->valor);
nodo = nodo->nodo_siguiente;
}
printf("\n");

return nodos;
}

// #define eliminar_pila(a) {if(pila_vacia(a))return;while(!pila_vacia(a))pop(a);}
void eliminar_pila(pila_ *pila) {
if(pila_vacia(pila)) return;
while(!pila_vacia(pila)) pop(pila);
return;
}


pila.h:
/*!
Miky Gonzalez Virtual Machine
Contact: mikygonzalez95@gmail.com

Miky Gonzalez Virtual Machine por Miky Gonzalez se encuentra bajo una
Licencia Creative Commons Atribución-NoComercial-CompartirIgual 3.0
Unported. Más información:
http://creativecommons.org/licenses/by-nc-sa/3.0/deed.es
*/

#ifndef MVM_PILA
#define MVM_PILA

/* Estructura de nodos de pila */
typedef struct NODO {
int valor;
struct NODO *nodo_siguiente;
} nodo_t;

typedef nodo_t *nodo_;
typedef nodo_t *pila_;

void push(pila_ *pila, int valor);
int pop(pila_ *pila);
unsigned short int pila_vacia(pila_ *pila);
unsigned short int contar_nodos(nodo_ nodo);
void eliminar_pila(pila_ *pila);

#endif


Actualmente no dispongo de tiempo para terminar el ensamblador, así que tendrán que crear los ejecutables editandolos hexadecimalmente, hice un programa para facilitarme el trabajo de prueba:

#include <stdio.h>

int main(int argc, char **argv) {
char codigo[] = {0x00};
FILE *fd;
fd = fopen("test", "wb");
if(!fd) return 0;
fwrite(codigo, sizeof(char), sizeof(codigo), fd);
fclose(fd);
return 0;
}





Algunos ejemplos ya programados, con sus respectivos opcodes:

#========================================
# CALCULAR RESTA DE DOS NUMEROS
#========================================
# Usando 2 registros se pueden hacer
# funciones de resta de números.
# resultado: r0
#========================================

# Inicializacion de los datos

lit 25 # ac: 25
store r0 # r0: 25
lit 17 # ac: 17
store r1 # r1: 17
lit 0 # ac: 0

# Bucles

load r1 # ac: r1
dec # ac: ac--
store r1 # r1: ac
load r0 # ac: r0
dec # ac: ac--
store r0 # r0: ac

lit 1 # ac: 1
cmpr r1 # comparar ac & r1
jmpg 16 # ac > r1 --> jmp 16
jmp 6 # jmp 6

halt # stop

# 0x01 25 0x03 0x00 0x01 17 0x03 0x01 0x01 0x00 0x02 0x01 0x05
# 0x03 0x01 0x02 0x00 0x05 0x03 0x00 0x01 0x01 0x0B 0x01 0x0F 28
# 0x0C 10 0x00


#========================================
# CALCULAR SUMA DE DOS NUMEROS
#========================================
# Usando 2 registros se pueden hacer
# funciones de suma de números.
# resultado: r0
#========================================

# Inicializacion de los datos

lit 17 # ac: 17
store r0 # r0: 17
lit 25 # ac: 25
store r1 # r1: 25
lit 0 # ac: 0

# Bucles

load r1 # ac: r1
dec # ac: ac--
store r1 # r1: ac
load r0 # ac: r0
inc # ac: ac++
store r0 # r0: ac

lit 1 # ac: 1
cmpr r1 # comparar ac & r1
jmpg 16 # ac > r1 --> jmp 16
jmp 6 # jmp 6

halt # stop
# 0x01 25 0x03 0x00 0x01 17 0x03 0x01 0x01 0x00 0x02 0x01 0x05
# 0x03 0x01 0x02 0x00 0x04 0x03 0x00 0x01 0x01 0x0B 0x01 0x0F 28
# 0x0C 10 0x00


#========================================
# CALCULAR MULTIPLICACION DE DOS NUMEROS
#========================================
# Utilizando 3 registros (incluso menos) se
# pueden hacer funciones de multiplicación
# de números.
# resultado: r2.
#========================================

# Inicialización de los datos

lit 10 # ac: 10
store r0 # r0: 10
lit 3 # ac: 3
store r1 # r1: 3
lit 0 # ac: 0


# Bucles

load r1 # ac: r1
dec # ac: ac--
store r1 # r1: ac
cmpl 0 # comparar ac & 0
jmpe 23 # ac == 0 --> jmp 23

lit 10 # ac: 10
store r0 # r0: 10

load r2 # ac: r2
inc # ac: ac++
store r2 # r2: ac
load r0 # ac: r0
dec # ac: ac--
store r0 # r0: ac
lit 0 # ac: 0
cmpr r0 # comparar ac & r0
jmpl 13 # ac < r0 --> jmp 13
jmp 6 # jmp 6

lit 0 # ac: 0
store r1 # r1: 0

halt # stop
#0x01 0x0A 0x03 0x00 0x01 0x03 0x03 0x01 0x01 0x00  
#0x02 0x01 0x05 0x03 0x01 0x0A 0x00 0x0D 0x29 0x01
#0x0A 0x03 0x00 0x02 0x02 0x04 0x03 0x02 0x02 0x00
#0x05 0x03 0x00 0x01 0x00 0x0B 0x00 0x0D 23 0x0C 10
#0x01 0x00 0x03 0x01 0x00


Espero que este proyecto les guste, y si alguien puede continuarlo, espero que lo haga y tenga buenas ideas, tal vez aunque no puedo no seria malo proponerlas, nunca se sabe si volvere a continuar con la máquina virtual.

Saludos,
  Miky Gonzalez
#36
Mi problema es el siguiente: supongamos que sólo tengo una función que me permite cojer 1 solo caracter numérico (getch() - 48). ¿Cómo podría hacer para cojer mas de un caracter?.

Si no lo entiendo les pongo un ejemplo: yo tengo una variable tipo entero. Hago que se guarde el valor devuelto por getch() a mi variable tipo entero. Algo como:
Introduce un numero: 4
Numero introducido: 4

El problema viene cuando:
Introduce un numero: 42
Numero introducido: 4

Como es de obviar, el 2 se queda en el buffer. Cómo puedo hacer, suponiendo que sólo tengo la función getch que sólo lee un caracter, la lectura de enteros (hasta encontrar caracter 0xA ('\n'). Supongamos tambien que el valor devuelto por getch() es de tipo entero.
#37
Exactamente como dice rir3760, la única forma portable es utilizando ese método (operaciones a nivel de bits). Comprobado por mi en varios compiladores (gcc [3.x] y gcc[4.x], visual c++, dev-cpp [mingw 3.6]). Los resultando en algunos casos, son "muy extraños" (se vacia buffer de entrada).
#38
Programación C/C++ / Re: [Opiniones] Máquina virtual
18 Septiembre 2013, 13:56 PM
Si, lose, pero la máquina virtual está programada en C/C++. Es por ello que quería las opiniones de que funciones servirían mejor, algoritmos de uso... para optimizar el código C.
#39
Programación C/C++ / [Opiniones] Máquina virtual
17 Septiembre 2013, 22:45 PM
Especificaciones de la máquina virtual:

El CPU virtual consta de varios registros:
4 registros utilizables a modo usuario, el registro acumulador (*), puntero de instrucción, memoria de código y memoria de datos y un último registro de tamaño byte usado para establecer comparaciones.

La memoria de datos, los 4 registros de usuario y el registro acumulador son de tipo short int, esto quiere decir que pueden alcanzar valores desde 0x0000 hasta 0xFFFF, menos la memoria, que alcanza valores desde 0x1000 hasta 0x2000 (esto son 4kB).

La memoria de datos está programada para en un futuro poder utilizar varias en una misma CPU usadas como "módulos". Para utilizarla un ejemplo podría ser:
putl 1001 BB (guardar en posicion 1 valor 0xBB).
Es posible que en un futuro se junten las dos memorias (memoria de código y memoria de datos).




Set de instrucciones:
0x00haltdetiene el cpu
0x01litcargar en acumulador un valor inmediato
0x02loadcargar en acumulador valor de un registro
0x03storealmacenar valor acumulador en un registro
0x04incincrementar por 1 el acumulador
0x05decdecrementar por 1 el acumulador
0x06putlponer en memoria un valor inmediato
0x07putrponer en registro un valor de memoria
0x08getacargar en acumulador un valor de memoria
0x09getrcargar en registro un valor de memoria
0x0Acmplcomparar acumulador con valor inmediado. establece flag
0x0Bcmprcomparar acumulador con valor registro. establece flag
0x0Cjmpsaltar a direccion de codigo (inicio == 0x00)
0x0Djmplsaltar a direccion de codigo si flag == 1 ( < )
0x0Ejmpesaltar a direccion de codigo si flag == 2 ( = )
0x0Fjmpg    saltar a direccion de codigo si flag == 3 ( > )



Programas de ejemplos (con sus opcodes)

#========================================
# CALCULAR RESTA DE DOS NUMEROS
#========================================
# Usando 2 registros se pueden hacer
# funciones de resta de números.
# resultado: r0
#========================================

# Inicializacion de los datos

lit 25 # ac: 25
store r0 # r0: 25
lit 17 # ac: 17
store r1 # r1: 17
lit 0 # ac: 0

# Bucles

load r1 # ac: r1
dec # ac: ac--
store r1 # r1: ac
load r0 # ac: r0
dec # ac: ac--
store r0 # r0: ac

lit 1 # ac: 1
cmpr r1 # comparar ac & r1
jmpg 16 # ac > r1 --> jmp 16
jmp 6 # jmp 6

halt # stop


char codigo[] = {0x01, 25, 0x03, 0x00, 0x01,
  17, 0x03, 0x01, 0x01, 0x00,
  0x02, 0x01, 0x05, 0x03, 0x01,
  0x02, 0x00, 0x05, 0x03, 0x00,
  0x01, 0x01, 0x0B, 0x01, 0x0F,
  28, 0x0C, 10, 0x00};


#========================================
# CALCULAR SUMA DE DOS NUMEROS
#========================================
# Usando 2 registros se pueden hacer
# funciones de suma de números.
# resultado: r0
#========================================

# Inicializacion de los datos

lit 17 # ac: 17
store r0 # r0: 17
lit 25 # ac: 25
store r1 # r1: 25
lit 0 # ac: 0

# Bucles

load r1 # ac: r1
dec # ac: ac--
store r1 # r1: ac
load r0 # ac: r0
inc # ac: ac++
store r0 # r0: ac

lit 1 # ac: 1
cmpr r1 # comparar ac & r1
jmpg 16 # ac > r1 --> jmp 16
jmp 6 # jmp 6

halt # stop


char codigo[] = {0x01, 17, 0x03, 0x00, 0x01,
  25, 0x03, 0x01, 0x01, 0x00,
  0x02, 0x01, 0x05, 0x03, 0x01,
  0x02, 0x00, 0x04, 0x03, 0x00,
  0x01, 0x01, 0x0B, 0x01, 0x0F,
  28, 0x0C, 10, 0x00};


#========================================
# CALCULAR MULTIPLICACION DE DOS NUMEROS
#========================================
# Utilizando 3 registros (incluso menos) se
# pueden hacer funciones de multiplicación
# de números.
# resultado: r2.
#========================================

# Inicialización de los datos

lit 10 # ac: 10
store r0 # r0: 10
lit 3 # ac: 3
store r1 # r1: 3
lit 0 # ac: 0


# Bucles

load r1 # ac: r1
dec # ac: ac--
store r1 # r1: ac
cmpl 0 # comparar ac & 0
jmpe 23 # ac == 0 --> jmp 23

lit 10 # ac: 10
store r0 # r0: 10

load r2 # ac: r2
inc # ac: ac++
store r2 # r2: ac
load r0 # ac: r0
dec # ac: ac--
store r0 # r0: ac
lit 0 # ac: 0
cmpr r0 # comparar ac & r0
jmpl 13 # ac < r0 --> jmp 13
jmp 6 # jmp 6

lit 0 # ac: 0
store r1 # r1: 0

halt # stop


char codigo[] = {0x01, 0x0A, 0x03, 0x00, 0x01,
  0x03, 0x03, 0x01, 0x01, 0x00,  
  0x02, 0x01, 0x05, 0x03, 0x01, 0x0A, 0x00,
  0x0D, 0x29,
  0x01, 0x0A, 0x03, 0x00, 0x02, 0x02, 0x04,
  0x03, 0x02, 0x02, 0x00, 0x05, 0x03, 0x00,
  0x01, 0x00, 0x0B, 0x00, 0x0D, 23, 0x0C,
  10, 0x01, 0x00, 0x03, 0x01, 0x00};





Espero opiniones, críticas y sus comentarios
#40
Ahí está el problema en la conversión por referencia, parece que se comete un bug en el gcc, porque en otras distros de gcc me funciona (lo recien acabo de comprobar, incluso en codepad), pero en la que yo uso no)... creo que no es problema de la programación, porque al convertir este a un short int, y almacenar el valor en un short int, al mostrarlo me devuelve un int.