elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Los 10 CVE más críticos (peligrosos) de 2020


  Mostrar Temas
Páginas: [1] 2 3
1  Programación / Programación C/C++ / [Idea] Librería para simplificar el uso de sockets en: 19 Noviembre 2014, 19:15 pm
Creo este tema para que aporten idea, una mejor solución o cualquier cosa que puedan aportar para mejorar esta pequeña idea.

En cuestión quiero crear una librería para simplificar el uso de sockets, en otra palabras, hacer las cosas más cómodamente.

La estructura general de la librería se compone de una estructura que almacena datos del socket; una estructura candidata posible podría ser algo como:

Código
  1. typedef int socket;
  2.  
  3. typedef struct libreria_socket {
  4. socket socket_fd;
  5. struct sockaddr_in host;
  6. } socket;

La segunda cosa fundamental será la inicialización de esa estructura. Para ello necesitamos 2 funciones auxiliares que recibirán los parametros directamente desde una función principal iniciar_socket; la primera de ellas crear_socket, supongamos que AF (Adress Format) es INET (IP y puerto): AF_INET; la segunda de ellas podría tener 2 variantes: iniciar_sockaddr e iniciar_sockaddrany. La diferencia de estas es que en la estructura sockaddr_in, sin_addr atendería en todo el rango: 127.0.0.1/24.

Funciones secundarias, que bien podrían servir para formar parte de una función principal que automatice el proceso dependiendo de las necesidades del usuario final ó para tener el código más organizado, limpio, estético y hacer las cosas más sencillas. Estas son las funciones conectar_socket, bind_socket, escuchar_socket, aceptar_socket (esta según lo anterior también podría tener dos variantes: aceptar_socket y aceptar_socket_addrany), cerrar_socket.

Las funciones de lectura y escritura pueden usarse nativamente. Un pseudocódigo de cómo funcionaría la librería según las ideas que tengo ahora mismo:

Código
  1. socket socket_test;
  2.  
  3. iniciar_socket(&socket_test, 8080 /* puerto */, "127.0.0.1" /* direccion ip */);
  4. conectar_socket(&socket_test);
  5.  
  6. char buffer[1024];
  7.  
  8. // Recibir datos
  9. read(socket_test.socket_fd, buffer, 1024);
  10.  
  11. // Reenviar datos
  12. write(socket_test.socket_fd, buffer, 1024);

De momento eso es todo. Aporten ideas, comentarios, soluciones, otra forma de hacerlo...

Saludos.
2  Programación / Programación C/C++ / [Opinion] Problema acerca de optimización en código - Uso dinámico de arrays en: 18 Noviembre 2014, 17:58 pm
Hoy recordando un tema que leí en éste mismo foro de Programación C/C++ acerca de la lectura de archivos y la interpretación de archivos de registros (LOGs) se me ha ocurrido programar un poco, una cosa ha derivado a la otra hasta que se me ha propuesto un problema acerca de la optimización del uso de arrays.

Es más rápido crear un array estático con los elementos suficientes (o más) del conjunto que queremos guardar. Por ejemplo, puedo crear un array de tipo char y tamaño 1024 para almacenar un texto de entrada y operar luego con él. Pero, ¿para qué reservar 1024 bytes si sólo usaré, por ejemplo, 8 bytes?. Entonces me puse a pensar en arrays dinámicos, en que por cada elemento valor añadido al conjunto llamaría a "realloc" para reservar el nuevo tamaño del conjunto, esto resulta muy lento. Una posible solución que se me ha ocurrido es reservar siguiendo como 2^n. Esto es:

  • Creo un array de tamaño 1
  • Inserto nuevo valor en array, para ello reservo 2^1 bytes
  • Inserto nuevo valor en array, para ello reservo 2^2 bytes, esto me permite añadir 1 elemento más sin necesidad de llamar a realloc (ya hay suficiente espacio para este elemento)
  • Si añado otro elemento más se reservan 2^3 bytes, esto es, tengo espacio para 4 elementos sin llamar a realloc

Con esto creo arrays dinámicos teniendo en cuenta la velocidad de proceso. La primera pregunta/duda/opininión me viene si hay una manera más optima teniendo en cuenta memoria/velocidad de procesamiento.

La siguiente preguntas es si existe una manera "organizada", tambien podria decirse como una manera adecuada, limpia, eficiente, de almacenar datos de todos los tipos reservando una N cantidad de memoria. Por ejemplo, si creo una estructura para el problema anterior para usar una "librería simple" de arrays dinámicos, la estructura usada para valores que contengan tipos enteros no me servirá para valores que contengan tipos char.

Existe alguna forma de hacer, en pseudocódigo:

Código
  1. Almacenar 4 bits
  2. # Con estos 4 bits puedo almacenar 4 tipos chars o un entero o un float...
  3. Insertar entero...
  4. O insertar char x 4...
  5. O insertar float...
3  Programación / Programación C/C++ / [Ayuda-C] Vectores y punteros (inicialización dinámica) en: 12 Noviembre 2014, 20:54 pm
Para el uso más cómodo de un programa en la creación de un simulador físico que requiere el uso de muchos vectores se me ha ocurrido crear una libreria para el manejo de los vectores. Comienzo definiendo la siguiente estructura:

Código
  1. typedef struct _vectf {
  2. float *data;
  3. int cap;
  4. } vectf;

Entonces para la creación del vector uso:

Código
  1. vectf v;

Y creo una función que inicialice el vector (reservar memoria y ajustar elementos):

Código
  1. int init_vectorf(vectf *vectorf, int capacity) {
  2. vectorf->data = malloc(capacity * sizeof(float));
  3. if(!vectorf->data)
  4. return 0;
  5.  
  6. vectorf->cap = sizeof(vectorf->data) / sizeof(vectorf->data[0]);
  7. //vectorf->cap = capacity;
  8. printf("sizeof(float) = %ld\n", sizeof(float));
  9. printf("Inicializado vectorf de tamano: %d (%d elementos).", (int)sizeof(vectorf->data), sizeof(vectorf->data) / sizeof(vectorf->data[0]));
  10.  
  11. return 1;
  12. }

En este paso se encuentra mi problema. Explicaré la idea del código para un mejor entendimiento:
1. Se reserva memoria para (n_elementos * tamaño_dato), esto es, si yo declaro:

Código
  1. init_vectorf(&vectorf, 3);

el cálculo sería: (3 * sizeof(float)), es decir, 3 elementos * 4 bytes = 12 bytes.

Cuando se hace la operación:
Código
  1. vectorf->cap = sizeof(vectorf->data) / sizeof(vectorf->data[0]);
la capacidad se establece a 3, como debería: memoria_total / tamaño_dato = 12 bytes / 4 bytes = 3 elementos.

El error viene que justamente despues al mostrarse la información de inicialización del vector escribe el siguiente mensaje en pantalla:

Código
  1. mikygonzalez@public_gpg ~/ $ Inicializado vectorf de tamano: 8 (2 elementos).

¿Alguien puede explicar porqué no me devuelve tamaño 12, 3 elementos?. Seguramente sea un error con los punteros ó el tamaño de datos, pero no soy capaz de localizarlo.

Saludos,
MikyGonzalez
4  Seguridad Informática / Hacking / Rompiendo la seguridad de Gilisoft USB Lock en: 26 Abril 2014, 13:19 pm
Gilisoft Usb Lock es un programa que nos permite entre muchas otras cosas bloquear el acceso USB y páginas web.

Su utilización es sencilla y tiene la posibilidad de introducir una contraseña de acceso para modificar sus configuraciones. Esta contraseña esta cifrada, y nosotros a traves del editor de registro podemos saber la contraseña (cifrada). No hace falta saber el algoritmo de cifrado, ya que cualquier valor que introduzcamos en el campo de contraseña equivale a un valor cifrado. A esto se le llama cifrado por diccionario (por ejemplo: a = 0x85, b = 0x86...). En esta situación se puede producir un ataque fácilmente porque el algoritmo de cifrado no determina ni la posición del carácter ni la longitud de la cadena.

Despues de ver el código del programa, se determina el siguiente diccionario:


Si es una contraseña larga y no merece buscar cual es el texto descifrado, podríamos sustituir todo el contenido por: 9e 00, equivalente a la contraseña "a" ('a'-'\0').

Una alternativa para ordenador que tienen eliminado/prohibido el uso del editor de registro, se puede utilizar el comando reg para interactuar con el registro; un ejemplo de su uso: reg import cambiar_clave_gilisoft.reg.

Para el uso con sistemas de 64Bits, el código a importar en registro sería como sigue:

Código
  1. Windows Registry Editor Version 5.00
  2. [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Gilisoft-usb-lock\configure]
  3. "datP"=hex:9e,00

32 Bits:

Código
  1. Windows Registry Editor Version 5.00
  2. [HKEY_LOCAL_MACHINE\SOFTWARE\Gilisoft-usb-lock\configure]
  3. "datP"=hex:9e,00
5  Programación / Programación C/C++ / [Ayuda-C] Algo falla... en: 12 Octubre 2013, 15:16 pm
Dado el siguiente código:

Código
  1. char lista_instrucciones[NUM_INSTR][10] = {
  2. {"PRINT"},
  3. {"SUM"},
  4. {"EXIT"}
  5. };
  6.  
  7. char *codigo = "PRINT BASURA!", *codigo2 = "EXIT TRASH";
  8.  
  9. void identificador_cadena(unsigned char *codigo) {
  10. unsigned short int pos_buffer = 0;
  11. char *buffer = (char *)malloc(1 * sizeof(char));
  12.  
  13. while(saber_letra(codigo[pos])) {
  14. buffer[pos_buffer] = codigo[pos];
  15. pos++;
  16. pos_buffer++;
  17. buffer = (char *)realloc(buffer, (pos_buffer + 1) * sizeof(char));
  18. }
  19.  
  20. buffer[pos_buffer] = '\0';
  21.  
  22. // Reutilizar variable pos_buffer
  23. for(pos_buffer = 0; pos_buffer < NUM_INSTR; pos_buffer++)
  24. if(!strcmp(buffer, lista_instrucciones[pos_buffer]))
  25. printf("Encontrado %s en %s\n", lista_instrucciones[pos_buffer], buffer);
  26.  
  27. free(buffer);
  28. return;
  29. }
  30.  

Se espera que al pasar las variables codigo y codigo2 a la función identificador_cadena, esta imprima en pantalla:

Código:
Encontrado PRINT en PRINT
Encontrado EXIT en EXIT

Pero en su lugar, imprime:
Código:
Encontrado SUM en PRINT
Encontrado EXIT en PRINT
Encontrado PRINT en EXIT
Encontrado SUM en EXIT

¿Alguien podría determinar el error?, no entiendo porque esto sucede
6  Programación / Programación C/C++ / [Codigo] Interesante codigo imprime numero primo de mayor cifras en: 12 Octubre 2013, 14:07 pm
Solo por interés, les dejo un código proveniente de una fuente web que les dejo más abajo:

Código
  1. #include <stdio.h>
  2.  
  3. int m = 1711276033, N = 1, t[1 << 25] = { 2 }, a, *p, i, e = 39717691, s, c, U = 1;
  4.  
  5. void g(int d, int h) {
  6. for(i = s; i < 1 << 24; i *= 2)
  7. d = d * 1LL * d % m;
  8. for(p = t; p < t + N; p += s)
  9. for(i = s, c = 1; i; i--)
  10. a = p[s] * (h ? c : 1LL) % m, p[s] = (m * 1U + *p - a) * (h ? 1LL : c) % m, *p = (a * 1U + *p) % m, p++, c = c * 1LL * d % m;
  11. }
  12.  
  13. int main() {
  14. while(e /= 2) {
  15. N *= 2;
  16. U = U * 1LL * (m + 1) / 2 % m;
  17. for(s = N; s /= 2;)
  18. g(40, 0);
  19. for(p = t; p < t + N; p++)
  20. *p = *p * 1LL ** p % m * U % m;
  21. for(s = 1; s < N; s *= 2)
  22. g(983983719, 1);
  23. for(a = 0, p = t; p < t + N;)
  24. a += *p << (e & 1), *p++ = a % 10, a /= 10;
  25. }
  26. while(!*--p);
  27. for(t[0]--; p >= t;)
  28. putchar(48 + *p--);
  29.  
  30. return 0;
  31. }
  32.  

[1] http://ijunkey.com/a-small-c-program-to-print-the-biggest-prime-number/
7  Programación / Programación C/C++ / [Ayuda-C] Bucle infinito en: 10 Octubre 2013, 18:43 pm
Estaba programando en C un ensamblador para programas de mi máquina virtual (decidí continuar un proyecto). Tengo el siguiente código:

Código
  1. /*! Ejemplo de lector de archivo */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5.  
  6. /*! Declaración de variables locales */
  7. enum {lex_PARI = '(', lex_PARD = ')', lex_LLAI = '{', lex_LLAD = '}'};
  8. unsigned short int pos = 0x00;
  9. unsigned int codigo_volumen;
  10. unsigned char *codigo;
  11. FILE *codigo_archivo;
  12.  
  13. void siguiente_lexema(unsigned char *codigo);
  14.  
  15. void buscar_caracter(char caracter) {
  16. while((caracter != codigo[pos]) && (pos < codigo_volumen)) {
  17. siguiente_lexema(codigo);
  18. pos++;
  19. }
  20. if(pos == codigo_volumen)
  21. printf("Se esperaba '%c'", caracter);
  22. }
  23.  
  24. // modo == 0 (si cadena)
  25. // modo == 1 (si entero)
  26. void identificador(unsigned char *codigo, char modo) {
  27.  
  28. return;
  29. }
  30.  
  31. int saber_letra(char caracter) {
  32. return (((caracter >= 'A') && (caracter <= 'Z')) || ((caracter >= 'a') && (caracter <= 'z')));
  33. }
  34.  
  35. int saber_numero(char caracter) {
  36. return ((caracter >= '0') && (caracter <= '9'));
  37. }
  38.  
  39. void siguiente_lexema(unsigned char *codigo) {
  40. switch(codigo[pos]) {
  41. case lex_PARI:
  42. printf("Encontrado: %c\n", lex_PARI);
  43. buscar_caracter(lex_PARD);
  44. break;
  45. case lex_LLAI:
  46. printf("Encontrado: %c\n", lex_LLAI);
  47. buscar_caracter(lex_LLAD);
  48. break;
  49. default:
  50. if(saber_letra(codigo[pos]))
  51. identificador(codigo, 0);
  52. else if(saber_numero(codigo[pos]))
  53. identificador(codigo, 1);
  54. /*
  55. * TODO: Mostrar error. Ignorar espacios, salto de línea y tabulador
  56. */
  57. else
  58. ;
  59. break;
  60. }
  61.  
  62. return;
  63. }
  64.  
  65. int main(int argc, char **argv) {
  66. if(argc < 2) {
  67. printf("Uso: %s <archivo>\n", argv[0]);
  68. return 0;
  69. }
  70. codigo_archivo = fopen(argv[1], "r");
  71. if(!codigo_archivo) {
  72. printf("[ASM] Error al leer el archivo %s\n", argv[1]);
  73. return 0;
  74. }
  75.  
  76. /* Calcular tamaño (volumen) del código */
  77. fseek(codigo_archivo, 0, SEEK_END);
  78. codigo_volumen = ftell(codigo_archivo);
  79. rewind(codigo_archivo);
  80. if(!codigo_volumen) {
  81. printf("[ASM] No hay instrucciones...\n");
  82. fclose(codigo_archivo);
  83. return 0;
  84. }
  85.  
  86. /* Reservar el espacio necesario para almacenar
  87. * el código en memoria. Si existe, copiarlo. */
  88. codigo = (unsigned char *)malloc(codigo_volumen);
  89. if(!fread(codigo, 1, codigo_volumen, codigo_archivo)) {
  90. printf("[ASM] Error en lectura de archivo...\n");
  91. fclose(codigo_archivo);
  92. return 0;
  93. } else fclose(codigo_archivo);
  94.  
  95. while(pos < codigo_volumen) {
  96. siguiente_lexema(codigo);
  97. pos++;
  98. }
  99.  
  100. return 0;
  101. }
  102.  

El problema está en que dado un archivo:

Código
  1. {
  2. {
  3. {
  4. ( {} )( } } }
  5.  

Entra en un bucle infinito. He revisado muchas veces el código pero no veo ningún error de direcciones, punteros... ¿Alguien puede determinar a causa de que?
8  Programación / Programación C/C++ / [C] Kernel - Contru...ctor en: 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
  1. .section multiboot
  2. // Cabezera multiboot
  3. .align 4
  4. .int 0x1badb002
  5. .int 0x0
  6. .int -0x1badb002
  7.  
  8. .section .text
  9.  
  10. // "init" es una función definida en init.c
  11. .extern init
  12.  
  13. // _start debe ser global, para que el enlazador pueda encontrarla y
  14. // usarla como punto de entrada.
  15. .global _start
  16. _start:
  17.    // Inicializar la pila
  18.    mov $kernel_stack, %esp
  19.  
  20.    // Llamar al código C
  21.    call init
  22.  
  23.    // Parar CPU - retorno desde código C
  24.    hlt
  25.  
  26. .section .bss
  27. .space 8192
  28. kernel_stack:
  29.  

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

Código
  1. void init(void) {
  2.    while(1) ;
  3. }

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
  1. /*  En _start debe iniciar la ejecución */
  2. ENTRY(_start)
  3. SECTIONS {
  4.    . = 0x100000;
  5.    .text : {
  6.        *(multiboot)
  7.        *(.text)
  8.    }
  9.    .data ALIGN(4096) : {
  10.        *(.data)
  11.    }
  12.    .rodata ALIGN(4096) : {
  13.        *(.rodata)
  14.    }
  15.    .bss ALIGN(4096) : {
  16.        *(.bss)
  17.    }
  18. }

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:

Código
  1. char *video = (char *) 0xB8000; // Dirección memoria video
  2. unsigned short int x = 0, y = 0; // Actual posición puntero
  3.  
  4. void putchar(char chr) {
  5.    if((chr == '\n') || (x > 79)) {
  6.        x = 0;
  7.        y++;
  8.    }
  9.    if(chr == '\n')
  10.        return;
  11.  
  12.    if(y > 24) {
  13.        int i;
  14.        for (i = 0; i < 2 * 24 * 80; i++)
  15.            video[i] = video[i + 160];
  16.  
  17.        for (; i < 2 * 25 * 80; i++)
  18.            video[i] = 0;
  19.        y--;
  20.    }
  21.  
  22.    video[2 * (y * 80 + x)] = chr;
  23.    video[2 * (y * 80 + x) + 1] = 0x07; // Color "default"
  24.  
  25.    x++;
  26.    return;
  27. }

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

Código
  1. int bucle_i;
  2. char *str1 = "Hola Mundo!"; // 11 carácteres
  3.  
  4. for(bucle_i = 0; bucle_i < 11; bucle_i++)
  5.    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:
Código
  1. void printf(char *str) {
  2.    int bucle_i = 0;
  3.  
  4.    for(; bucle_i < strlen(str); bucle_i++)
  5.        putchar(str[bucle_i]);
  6. }

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

[FUENTES]

 Saludos,
     MikyGonzalez
9  Programación / Programación C/C++ / [Código fuente][C] Máquina virtual en: 30 Septiembre 2013, 18:30 pm
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:
Código
  1. /*!
  2. Miky Gonzalez Virtual Machine
  3. Contact: mikygonzalez95@gmail.com
  4.  
  5. Miky Gonzalez Virtual Machine por Miky Gonzalez se encuentra bajo una
  6. Licencia Creative Commons Atribución-NoComercial-CompartirIgual 3.0
  7. Unported. Más información:
  8. http://creativecommons.org/licenses/by-nc-sa/3.0/deed.es
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. //#include <inttypes.h>
  15. //#include <time.h>
  16.  
  17. #include "pila.h"
  18.  
  19. /* MVM - Estructura de la MV */
  20. typedef struct CPU {
  21. short int registro[4];
  22. short int acumulador;
  23. unsigned int inst_pointer;
  24. unsigned char *memoria_codigo;
  25. unsigned char flag;
  26. pila_ pila;
  27. } cpu_t;
  28.  
  29. unsigned int crear_cpu(cpu_t *cpu, unsigned char *memoria_codigo) {
  30. if(!memoria_codigo || !cpu) return 0;
  31.  
  32. //memset(cpu->registro, 0, sizeof(cpu->registro) / sizeof(*cpu->registro));
  33. unsigned short int i = 0;
  34. for(; i < 4; i++)
  35. cpu->registro[i] = 0;
  36. cpu->acumulador = 0;
  37. cpu->inst_pointer = 0;
  38. cpu->memoria_codigo = memoria_codigo;
  39. cpu->flag = 0;
  40. cpu->pila = NULL;
  41.  
  42. return 1;
  43. }
  44.  
  45. void ejecutar_cpu(cpu_t *cpu) {
  46. if(!cpu) {
  47. printf("[MVM] Error al ejecutar CPU...\n");
  48. return;
  49. }
  50. while(1) {
  51. switch(cpu->memoria_codigo[cpu->inst_pointer]) {
  52. case 0x00: /*! halt */
  53. printf("halt\n");
  54. return;
  55. case 0x01: /*! lit */
  56. cpu->acumulador = cpu->memoria_codigo[++cpu->inst_pointer];
  57. printf("lit %d\n", cpu->memoria_codigo[cpu->inst_pointer]);
  58. break;
  59. case 0x02: /*! load */
  60. if(cpu->memoria_codigo[++cpu->inst_pointer] > 0x03) {
  61. printf("[CPU] Desbordamiento en numero de registro.\n");
  62. return;
  63. }
  64. cpu->acumulador = cpu->registro[cpu->memoria_codigo[cpu->inst_pointer]];
  65. printf("load r%d\n", cpu->memoria_codigo[cpu->inst_pointer]);
  66. break;
  67. case 0x03: /*! store */
  68. if(cpu->memoria_codigo[++cpu->inst_pointer] > 0x03) {
  69. printf("[CPU] Desbordamiento en numero de registro.\n");
  70. return;
  71. }
  72. cpu->registro[cpu->memoria_codigo[cpu->inst_pointer]] = cpu->acumulador;
  73. printf("store r%d\n", cpu->memoria_codigo[cpu->inst_pointer]);
  74. break;
  75. case 0x04: /*! inc */
  76. cpu->acumulador++;
  77. printf("inc\n");
  78. break;
  79. case 0x05: /*! dec */
  80. cpu->acumulador--;
  81. printf("dec\n");
  82. break;
  83. case 0x06: /*! pushl */
  84. push(&cpu->pila, cpu->memoria_codigo[++cpu->inst_pointer]);
  85. printf("pushl %d\n", cpu->memoria_codigo[cpu->inst_pointer]);
  86. break;
  87. case 0x07: /*! pushr */
  88. if(cpu->memoria_codigo[++cpu->inst_pointer] > 0x03) {
  89. printf("[CPU] Desbordamiento en numero de registro.\n");
  90. return;
  91. }
  92. push(&cpu->pila, cpu->registro[cpu->memoria_codigo[cpu->inst_pointer]]);
  93. printf("pushr r%d\n", cpu->memoria_codigo[cpu->inst_pointer]);
  94. break;
  95. case 0x08: /*! pop */
  96. if(pila_vacia(&cpu->pila)) {
  97. printf("[CPUSTACK] No hay elemento en pila.\n");
  98. return;
  99. }
  100. pop(&cpu->pila);
  101. printf("pop\n");
  102. break;
  103. case 0x09: /*! loadt */
  104. if(pila_vacia(&cpu->pila)) {
  105. printf("[CPUSTACK] No hay elemento en pila.\n");
  106. return;
  107. }
  108. cpu->acumulador = pop(&cpu->pila);
  109. printf("loadt\n");
  110. break;
  111. case 0x0A: /*! cmpl */
  112. if(cpu->acumulador < cpu->memoria_codigo[++cpu->inst_pointer])
  113. cpu->flag = 1;
  114. else if(cpu->acumulador == cpu->memoria_codigo[cpu->inst_pointer])
  115. cpu->flag = 2;
  116. else if(cpu->acumulador > cpu->memoria_codigo[cpu->inst_pointer])
  117. cpu->flag = 3;
  118. printf("cmpl %d\n", cpu->memoria_codigo[cpu->inst_pointer]);
  119. break;
  120. case 0x0B: /*! cmpr */
  121. if(cpu->acumulador < cpu->registro[cpu->memoria_codigo[++cpu->inst_pointer]])
  122. cpu->flag = 1;
  123. else if(cpu->acumulador == cpu->registro[cpu->memoria_codigo[cpu->inst_pointer]])
  124. cpu->flag = 2;
  125. else if(cpu->acumulador > cpu->registro[cpu->memoria_codigo[cpu->inst_pointer]])
  126. cpu->flag = 3;
  127. printf("cmpr r%d\n", cpu->memoria_codigo[cpu->inst_pointer]);
  128. break;
  129. case 0x0C: /*! jmp */
  130. printf("jmp %d\n", cpu->memoria_codigo[++cpu->inst_pointer]);
  131. cpu->inst_pointer = cpu->memoria_codigo[cpu->inst_pointer] - 1;
  132. break;
  133. case 0x0D: /*! jmpl */
  134. printf("jmpl %d\n", cpu->memoria_codigo[++cpu->inst_pointer]);
  135. if(cpu->flag == 1)
  136. cpu->inst_pointer = cpu->memoria_codigo[cpu->inst_pointer] - 1;
  137. break;
  138. case 0x0E: /*! jmpe */
  139. printf("jmpe %d\n", cpu->memoria_codigo[++cpu->inst_pointer]);
  140. if(cpu->flag == 2)
  141. cpu->inst_pointer = cpu->memoria_codigo[cpu->inst_pointer] - 1;
  142. break;
  143. case 0x0F: /*! jmpg */
  144. printf("jmpg %d\n", cpu->memoria_codigo[++cpu->inst_pointer]);
  145. if(cpu->flag == 3)
  146. cpu->inst_pointer = cpu->memoria_codigo[cpu->inst_pointer] - 1;
  147. break;
  148. default:
  149. printf("[CPU] Instruccion desconocida. Cerrando proceso CPU.\n");
  150. return;
  151. }
  152. cpu->inst_pointer++;
  153. 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);
  154. contar_nodos(cpu->pila);
  155. }
  156. }
  157.  
  158. int main(int argc, char *argv[]) {
  159. /* Inicializar datos y comprobar argumentos */
  160. if(argc < 2) {
  161. printf("Uso: %s <archivo>\n", argv[0]);
  162. return 0;
  163. }
  164. FILE *codigo_archivo = fopen(argv[1], "rb");
  165. if(!codigo_archivo) {
  166. printf("[MVM] Fallo al abrir el archivo %s\n", argv[1]);
  167. return 0;
  168. }
  169.  
  170. /* Calcular tamaño (volumen) del código */
  171. unsigned int codigo_volumen;
  172. fseek(codigo_archivo, 0, SEEK_END);
  173. codigo_volumen = ftell(codigo_archivo);
  174. rewind(codigo_archivo);
  175. if(!codigo_volumen) {
  176. printf("[MVM] No hay instrucciones...\n");
  177. fclose(codigo_archivo);
  178. return 0;
  179. }
  180.  
  181. /* Reservar el espacio necesario para almacenar
  182. * el código en memoria. Si existe, copiarlo. */
  183. unsigned char *codigo = (unsigned char *)malloc(codigo_volumen);
  184. if(!fread(codigo, 1, codigo_volumen, codigo_archivo)) {
  185. printf("[MVM] Error en lectura de archivo...\n");
  186. fclose(codigo_archivo);
  187. return 0;
  188. } else fclose(codigo_archivo);
  189.  
  190. /* Crear CPU e inicializar los datos */
  191. cpu_t cpu;
  192. if(!crear_cpu(&cpu, codigo)) {
  193. printf("[MVM] Error al crear CPU...\n");
  194. return 0;
  195. }
  196.  
  197. /* Ejecutar CPU hasta instrucción fin o error */
  198. ejecutar_cpu(&cpu);
  199. 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);
  200. contar_nodos(cpu.pila);
  201. eliminar_pila(&cpu.pila);
  202. free(codigo);
  203.  
  204. return 0;
  205. }

pila.c:
Código
  1. /*!
  2. Miky Gonzalez Virtual Machine
  3. Contact: mikygonzalez95@gmail.com
  4.  
  5. Miky Gonzalez Virtual Machine por Miky Gonzalez se encuentra bajo una
  6. Licencia Creative Commons Atribución-NoComercial-CompartirIgual 3.0
  7. Unported. Más información:
  8. http://creativecommons.org/licenses/by-nc-sa/3.0/deed.es
  9. */
  10.  
  11. /*! Implementación de una pila para memoria de datos MVM */
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include "pila.h"
  16.  
  17. void push(pila_ *pila, int valor) {
  18. nodo_ nodo = (nodo_)malloc(sizeof(nodo_t));
  19.  
  20. if(nodo != NULL) {
  21. nodo->valor = valor;
  22. nodo->nodo_siguiente = *pila;
  23. *pila = nodo;
  24. }
  25. }
  26.  
  27. int pop(pila_ *pila) {
  28. nodo_ nodo;
  29. int valor = 0;
  30.  
  31. nodo = *pila;
  32. valor = (*pila)->valor;
  33. *pila = (*pila)->nodo_siguiente;
  34.  
  35. free(nodo);
  36. return valor;
  37. }
  38.  
  39. //#define pila_vacia(a) *a == NULL ? 1:0;
  40. unsigned short int pila_vacia(pila_ *pila) {
  41. return (*pila == NULL ? 1 : 0);
  42. }
  43.  
  44. unsigned short int contar_nodos(nodo_ nodo) {
  45. if(nodo == NULL) return 0;
  46.  
  47. unsigned short int nodos = 0;
  48. while(nodo != NULL) {
  49. nodos++;
  50. printf("n%d: %d\t", nodos, nodo->valor);
  51. nodo = nodo->nodo_siguiente;
  52. }
  53. printf("\n");
  54.  
  55. return nodos;
  56. }
  57.  
  58. // #define eliminar_pila(a) {if(pila_vacia(a))return;while(!pila_vacia(a))pop(a);}
  59. void eliminar_pila(pila_ *pila) {
  60. if(pila_vacia(pila)) return;
  61. while(!pila_vacia(pila)) pop(pila);
  62. return;
  63. }

pila.h:
Código
  1. /*!
  2. Miky Gonzalez Virtual Machine
  3. Contact: mikygonzalez95@gmail.com
  4.  
  5. Miky Gonzalez Virtual Machine por Miky Gonzalez se encuentra bajo una
  6. Licencia Creative Commons Atribución-NoComercial-CompartirIgual 3.0
  7. Unported. Más información:
  8. http://creativecommons.org/licenses/by-nc-sa/3.0/deed.es
  9. */
  10.  
  11. #ifndef MVM_PILA
  12. #define MVM_PILA
  13.  
  14. /* Estructura de nodos de pila */
  15. typedef struct NODO {
  16. int valor;
  17. struct NODO *nodo_siguiente;
  18. } nodo_t;
  19.  
  20. typedef nodo_t *nodo_;
  21. typedef nodo_t *pila_;
  22.  
  23. void push(pila_ *pila, int valor);
  24. int pop(pila_ *pila);
  25. unsigned short int pila_vacia(pila_ *pila);
  26. unsigned short int contar_nodos(nodo_ nodo);
  27. void eliminar_pila(pila_ *pila);
  28.  
  29. #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:

Código
  1. #include <stdio.h>
  2.  
  3. int main(int argc, char **argv) {
  4. char codigo[] = {0x00};
  5. FILE *fd;
  6. fd = fopen("test", "wb");
  7. if(!fd) return 0;
  8. fwrite(codigo, sizeof(char), sizeof(codigo), fd);
  9. fclose(fd);
  10. return 0;
  11. }



Algunos ejemplos ya programados, con sus respectivos opcodes:

Código:
#========================================
# 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

Código:
#========================================
# 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

Código:
#========================================
# 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
10  Programación / Programación C/C++ / [Ayuda-C] Leer entero desde stdin en: 28 Septiembre 2013, 12:01 pm
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:
Código
  1. Introduce un numero: 4
  2. Numero introducido: 4
El problema viene cuando:
Código
  1. Introduce un numero: 42
  2. 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.
Páginas: [1] 2 3
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines