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

#41
Sólo tengo un problema, y es que mi matriz declarada tiene que ser declarada como char. De ahí el problema:
0xAA, 0xBB declarados ambos como char deben pasar a ser 0xAABB. :S
#42
Programación C/C++ / [Ayuda] Conversiones *char - int
17 Septiembre 2013, 17:43 PM
Supongamos que yo tengo la siguiente matriz:

char codigo[] = {0x00, 0xFF, 0x01, 0x03, 0x01, 0xFF, 0xFF, 0x00};

Con esta matriz se podrian hacer muchas cosas, desde interpretarla, hasta leer numeros. Mi pregunta:

En la posición 5 (recordar que empieza desde 0) y en la 6 hay 0xFF. Perfectamente podria poner en numero entero como 256, 256. Pero mi cuestion es: ¿Cómo puedo leer esos dos 0xFF, para que me queden como un 0xFFFF (tamaño de short int). Para que me entiendan, si hubiera: 0x4F, 0x33; quedaria: 0x4F33.

Se me ocurrieron varias opciones como: (0x4F << 2) &  0x33, pero ningun me funciona. ¿Podrían ayudarme?
#43
Llevo ya desarroyando una máquina virtual largo tiempo, pero no tengo mucho tiempo, estoy con otros proyectos más importantes. Las funciones actuales (no creo que implemente alguna función más, sólo características y ampliaciones):




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
0x06pushlponer en pila un valor inmediato
0x07pushrponer en pila valor de un registro
0x08popeliminar 'cima de pila' (tos)
0x09loadtalmacenar valor retorno de pop en acumulador
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 ( > )



No es un juego de instrucciones completo ni facil de usar, pero teoricamente cualquier otra operación se puede hacer con esas instrucciones, de echo, hice una operación de multiplicar dos números (30 * 3):

Código (asm) [Seleccionar]
#========================================
# CALCULAR MULTIPLICACION DE DOS NUMEROS
#========================================
# Utilizando tres registros se
# pueden hacer funciones de multiplicación
# de números.
#========================================

# 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


A la hora de ser compilado para la máquina virtual, queda una matriz como:
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};


Cuya alternativa en código C:
int num1, num2 = 3;
int mult = 0;

for (; num2 > 0; num2--) {
for(num1 = 10; num1 > 0; num1--) {
mult++;
}
}





Pueden si quieres crear sus propios algoritmos y postearlos en este mensaje, me ayudaría mucho, estoy intentando implementar "funciones externas", un archivo que incluya funciones para simplificar el trabajo. Esto es una multiplicación simple, seguramente se puede hacer optimizable y/o más corta, cualquier código que quieran crear utilizando esas funciones me ayudaria para probar la máquina virtual.

En aproximadamente 2 semanas espero publicar el código fuente completo... no me gusta sacar 100 versiones para una aplicacion!

Saludos
#44
Entiendo lo que quieren decir, gracias por comentar.

Anotando, el ejercicio es puesto para C, no soy amigo de C++. Y la idea esque el que quiera lo utilice si no tiene nada que hacer e incluso podria sacar una libreria propia de numeros reales de tamaño ilimitado (aka GMP).

Saludos
#45
Supongamos por un momento que debes hacer un programa que calcule, lo más exactamente posible, una media, o cálculos, que de seguro, tendrán decimales. Sólo hay una pega, no puedes usar el tipo float bajo ningún concepto.

Lo mejor para este ejercicio sería crear un archivo de cabezera que incluya estructura para crear tu propio tipo float basandote en tipos enteros. Hacer eso es muy facil:


typedef struct _real {
       int entero;
       unsigned long int decimal;
} real_t;


Pero se deben crear tambien unas funciones que nos permita actuar con sencillez, como si de un tipo entero se tratase. Puedes empezar por estas funciones:


real_t declarar_real(int entero, unsigned long int decimal) {
   real_t real;    

   real.entero = entero;
   real.decimal = decimal;

   return real;
}

#define mostrar_real(a) printf("%d.%u", a.entero, a.decimal)


Lo que se pide en este ejercicio, para quienes quieran hacerlo para practicar sus conocimientos:
Crear funciones de suma y resta de numeros tipo real, al igual que funciones de multiplicación y división.
Si has echo lo anterior, prueba a modificar la estructura para que admita un número ilimitado de decimales (podrías hacerlo con una matriz dinámica).
#46
Gracias por comentar, leo todos los comentarios, aunque no siempre tengo tiempo para contestar.
Leí todas las indicaciones y miré algunas máquinas virtual y frameworkd como lo son la JVM y la plataforma .NET. Algunas notaciones que pusistes me parecieron útiles, que no pensé demasiado en ellas. El analizador léxico-sintáctico lo estoy programando en este instante, pero el tema de los espacios, saltos de línea no es de momento inconveniente, funcionando de la siguiente forma y manera:
1. Leo el archivo y paso su contenido (exceptuando comentarios ' y '= hasta =') a un buffer dinámico (así me aseguro).
2. Hago un parser inicial eliminando datos "obvios/inutiles", como son espacios entre funciones, declaraciones; respetando las reglas de conducta que se deben seguir. En esta etapa se deben precalcular resultados (por ejemplo add r1 (23+2+32+3+2),(23+2+3+2)).
3. Hago un segundo parser comprobando sintexis y pasando a opcode y guardando estos en un archivo. Por supuesto, está echo para que el fichero contenga toda la información y ocupe lo menos posible.

Es la forma más rápida, eficiente y limpia que encontré de programar el conversor a opcodes.

Para aclararte, no esta en mis pensamientos incluir una función para copiar el valor de un registro en otro. Como especifico, puedes hacer una subrutina a forma de libreria libre. Por supuesto, que todas las librerias que se usen a modo de API, serán libres, y espero que la máquina virtual tambien. De momento no puedo poner el código, pero si quieres echarle un vistazo, contactame.

He decidido modificar el proyecto para seguir otro camino, pero sin salirse del camino de aprender y hacer aprender. Pongo los cambios y las nuevas especificaciones:
La utilización de registros, tratándose de ellos, ahora se utilizará (como antes) precedida del carácter 'r'. La utilización de valores numéricos se especificará con '#'. Por ejemplo:
  add r2 r5 #50 ' guarda en el registro 2 la suma del registro 5 más 50 (decimal)

Implementaré funciones simples (que pueden dar lugar a funciones complejas) de utilización de posiciones de memoria dentro de la máquina virtual (punteros para acceder a ellas). Para especificar una posición de memoria debe utilizarse el carácter @: @1000 ' posicion de memoria 1000 (decimal).

Una especificación que me faltó de dar en el post principal es la generación de los opcodes, como es por ejemplo: una función sin parámetros utiliza un byte de tamaño: 0x00. Si utiliza parámetros, dependiendo de estos: 0x00 0x00 0x00 (funcion param1 param2).

  Función 'halt' - Tendra el opcode 0x00. Obviamente, esto detendrá la máquina virtual cualquier punto en que esta se encuentre. Tiene como opcode 0x00 porque supongamos que hay un error de programación y se empieza a leer fuera de memoria, la mayor parte de esta esta llena de ceros.

La idea que tuve es en hacer que los elementos de la pila tengan dirección de memoria (virtual en la máquina virtual), al ejemplo del elemento 1 (el último añadido) tendría la última dirección de memoria posible. Esto es así porque la pila se llena desde abajo.

Saludos,
   Miky Gonzalez
#47
Me gustaría que me diesen alguna opinión acerca de las implementaciones actuales y en el apartado 'para hacer' las ideas que tengo. La máquina virtual está programada y es rápida. Usa memoria dinámica para el uso de registros y la pila. Pronto intentaré implementar para el uso de API y añadir funcionalidades propias sin modificar código interno.

Expecificaciones del lenguaje:
Se trata de un microlenguaje de programación ensamblador orientado al uso de pila, registros y operaciones aritméticas. Esta diseñado con el mero propósito de aprender.

Dispone de 8 registros (r0-r7)(tipo entero), elegidos así porque me parece un número de registros adecuado. No admite cadenas de caracteres ni números reales. Es un lenguaje semicompilado, es decir, sus intrucciones son transmitidas a opcodes que son emulados por una máquina virtual (actualmente, la
máquina virtual ya está en una buena fase de desarrollo).

Algunas especificaciones técnicas del lenguaje:
   · Debe respetarse el orden de parámetros
   · Los registros son numerados desde 0 a 7, indicando que es un registro con la letra 'r' precediendo al número.
   · Para definir el inicio del programa debera utilizarse la etiqueta %main% precedida de las intrucciones.
   · Para definir el fin del programa debera utilizarse la etiqueta %end main%
   · Para definir una funcion común (no implementado) deberá utilizarse la etiqueta %nombredefuncion,parametro1,param...% finalizando esta con %end nombredefuncion%
   · Pueden incluirse comentarios en el código con ' y '= ='.
   · Cada línea tendrá como máximo una función
   · Pueden definirse 'cotas' de código para hacer el código más pequeño, compartiendo biblioteca que pueden ser incluidas en el código con %include archivo.mvm%. Se dispondrá de version estándar  de algunas implementaciones para agilizar el uso y ampliar las funciones con el uso de API.

Función 'setr' - Establece el valor a un registro:
   setr [r0-r7] num1      ' Uso normal

Función 'add' - Función con la capacidad de sumar 2 enteros y guardar la operación en el registro indicado:
   add [r0-r7] num1,num2   ' Uso normal
   
Función 'addr' - Suma 2 enteros, uno de ellos dado por el valor de un registro. Con las funciones add y addr pueden hacerse todas las operaciones de suma desde sumar dos registros hasta sumar registro con datos de la pila:
   addr [r0-r7] rX,rX      ' Uso normal
   
Función 'neg' - Niega el valor de un registro dado:
   neg [r0-r7]            ' Uso normal
   
El equivalente a la función 'sub' se puede utilizar conjuntamente con 'addr' y 'neg':
   '= Queremos restar r1 - r0 y guardar valor en r3 ='
   neg r0
   addr r3 r1 r0
   
Función 'mult' - Multiplica 2 enteros y guarda la operación en el registro dado:
   mult [r0-r7] num1,num2   ' Uso normal
   
Función 'multr' - Multiplica el valor de 2 registros y guarda la  operación en el registro dado:
   multr [r0-r7] rX,rX      ' Uso normal
   
Función 'push' - Pone el valor de un registro en pila:
   push [r0-r7]         ' Uso normal
   
Función 'pop' - Elimina el tos:
   pop                  ' Uso normal

Función 'inrp' - Intercambia el valor de un registro y del tos:
   inrp [r0-r7]         ' Uso normal

El equivalente a 'inrr' (intercambiar dos registros, mov), puede hacerse con funciones ya descritas:
   '= Queremos intercambiar r0 y r1. Vamos a suponer que todos los
   registros tienen valores que deben ser guardados. ='
   push r0
   inrp r1
   inrp r0
   pop

Otra utilidad que tiene las funciones anteriores, no se necesita de función 'clonr' (clonar valor de un registro en otro), ya que, esta podria hacerse de muchas otras maneras con inrp o addr.

Función 'cmp' - Comparar si el valor de un registro y un valor proporcionado son iguales, mayor, menor (con respecto al registro):
   cmp [r0-r7]   num1      ' Uso normal

Función 'cmpr' - Comparar si el valor de dos registros son iguales, mayor, o menor (con respecto al primer registro):
   cmpr [r0-r7] [r0-r7]   ' Uso normal

Para hacer:
Cambiar la forma de analizar las funciones, para evitar usar funciones clonadas para operar con registros (add, addr, mult, multr...); Así, se podrá operar con los registros de una forma más fácil y comoda.
Añadir funciones condicionales, uso de cadenas, operaciones con cadenas.
Ampliar numero de funciones aritméticas (shl, shr, xor, div, mod...).
#48
Buenas a todos, inicio un nuevo POST para pedirles ayuda sobre la programación de un analizador léxico-sintáctico. No entiendo los códigos que vi por ahí, o si los entiendo, son demasiados complejos para implementarlos y hacer una adaptación.

Les pondré un ejemplo si no entienden lo que quiero conseguir. Supongamos un fichero de texto como el que sigue:

var
    int a, b, c;
    string d, e, f;
begin
    print("hola")
end


El desglosamiento del programa podría seguir un arbol como:

Declarar variables
   |-a como entero
   |-b como entero
   |-c como entero
   |-d como cadena
   |-e como cadena
   |-f como cadena
Iniciar ejecucion
   |- llamar funcion print con argumento hola como cadena
Fin ejecucion


Y que eso me genere unos ciertos opcodes, (no es necesario que el programa genere el arbol anterior), por ejemplo podria ser:
0x00 a (declarar int a), 0x00 b (declarar int b) ... 0x01 d (declarar string d) ... 0x02 "hola" (llamar funcion print con argumento hola).

No se como implementar esto en C. ¿Alguien puede ayudarme?

Saludos,
   Miky Gonzalez
#49
A mi, el programa, a mi entender, podría quedar algo como lo que sigue. Sería una muy buena forma de implementarlo y trabajar con punteros y demás, que es lo que más suele costar al principio:

CitarHola amigos mi pregunta es la siguiente, tengo 4 vendedores de los cuales debo guardar uno por uno, nombre, numero de ventas, codigo y descripcion y motrarlo por pantalla y mostrar las ventas totales de todos los vendedores, pero al final debo mostrar cual vendedor tiene el record de haber vendido mas articulos y en eso es que tengo el problema por favor ayudenme a solucionarlo se los agradezco, aqui les dejo lo que eh hecho. 

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

#define NUM_VENDEDORES 4

typedef struct vendedores {
    char *nombre;
    unsigned int numero_ventas;
    unsigned int codigo;
    char *descripcion; // 255chr + \0
} vendedores_t;

int main(int argc, char **argv) {
    vendedores_t *vendedor = malloc(sizeof(vendedores_t) * 4);
    unsigned int bucle_i = 0;
   
    while(bucle_i < 4) {
printf("Ingrese los datos para vendedor %d (nombre - ventas - codigo - desc): ", bucle_i + 1);
scanf("%s %i %i %s", vendedor[bucle_i].nombre, &vendedor[bucle_i].numero_ventas, &vendedor[bucle_i].codigo, vendedor[bucle_i].descripcion);
#50
Puedes, para practicar, hacer una función para comparar 4 números y retornar el mayor:

int retornar_mayor(int a, int b, int c, int d) {
   if((a > b) && (a > c) && (a > d)
       return a;
   else if((b > c) && (b > d))
       return b;
   else if(c > d)
       return c;
   else
       return d;
}


Si quieres practicar con el preprocesador de C, puedes hacer que en vez de función sea una directiva. Esto lo puedes hacer como:

#define COMPARAR(a, b, c, d) if((a > b) && (a > c) && (a > d) printf("%d", a); \
    else if((b > c) && (b > d)) printf("%d", b); \
    else if(c > d) printf("%d", c); \
    else printf("%d", d);


Para llamar a esta función es muy sencillo; Por ejemplo, podrías hacer:

retornar_mayor(vend_1, vend_2, vend_3, vend_4);

Esto te retornará el valor mayor de todos los vendedores, pero no te dirá cuál es. Puede modificar la función para que te retorne una matriz con el nombre del vendedor y su valor:

char** lista; // char lista[][];
lista[][] = {{"VENDEDOR", "50"}}; // Un ejemplo en bruto


Para retornar una matriz (sea de la dimensión que sea) debes retornar un puntero hacia la matriz.