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

 

 


Tema destacado: Estamos en la red social de Mastodon


  Mostrar Mensajes
Páginas: 1 2 3 [4] 5 6 7 8 9
31  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
32  Programación / Programación C/C++ / Re: Numeros primos en: 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  Programación / Programación C/C++ / Re: [Código fuente][C] Máquina virtual en: 2 Octubre 2013, 14:01 pm
Totalmente de acuerdo con todos ustedes, si continuo el proyecto, intentaré implementar lo mejor posible para optimizar en velocidad.
  Saludos
34  Programación / Programación C/C++ / Re: [Código fuente][C] Máquina virtual en: 30 Septiembre 2013, 21:24 pm
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  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
36  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.
37  Programación / Programación C/C++ / Re: [Ayuda] Conversiones *char - int en: 19 Septiembre 2013, 21:25 pm
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 / Programación C/C++ / Re: [Opiniones] Máquina virtual en: 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 / Programación C/C++ / [Opiniones] Máquina virtual en: 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)

Código
  1. #========================================
  2. # CALCULAR RESTA DE DOS NUMEROS
  3. #========================================
  4. # Usando 2 registros se pueden hacer
  5. # funciones de resta de números.
  6. # resultado: r0
  7. #========================================
  8.  
  9. # Inicializacion de los datos
  10.  
  11. lit 25 # ac: 25
  12. store r0 # r0: 25
  13. lit 17 # ac: 17
  14. store r1 # r1: 17
  15. lit 0 # ac: 0
  16.  
  17. # Bucles
  18.  
  19. load r1 # ac: r1
  20. dec # ac: ac--
  21. store r1 # r1: ac
  22. load r0 # ac: r0
  23. dec # ac: ac--
  24. store r0 # r0: ac
  25.  
  26. lit 1 # ac: 1
  27. cmpr r1 # comparar ac & r1
  28. jmpg 16 # ac > r1 --> jmp 16
  29. jmp 6 # jmp 6
  30.  
  31. halt # stop

Código
  1. char codigo[] = {0x01, 25, 0x03, 0x00, 0x01,
  2.   17, 0x03, 0x01, 0x01, 0x00,
  3.   0x02, 0x01, 0x05, 0x03, 0x01,
  4.   0x02, 0x00, 0x05, 0x03, 0x00,
  5.   0x01, 0x01, 0x0B, 0x01, 0x0F,
  6.   28, 0x0C, 10, 0x00};

Código
  1. #========================================
  2. # CALCULAR SUMA DE DOS NUMEROS
  3. #========================================
  4. # Usando 2 registros se pueden hacer
  5. # funciones de suma de números.
  6. # resultado: r0
  7. #========================================
  8.  
  9. # Inicializacion de los datos
  10.  
  11. lit 17 # ac: 17
  12. store r0 # r0: 17
  13. lit 25 # ac: 25
  14. store r1 # r1: 25
  15. lit 0 # ac: 0
  16.  
  17. # Bucles
  18.  
  19. load r1 # ac: r1
  20. dec # ac: ac--
  21. store r1 # r1: ac
  22. load r0 # ac: r0
  23. inc # ac: ac++
  24. store r0 # r0: ac
  25.  
  26. lit 1 # ac: 1
  27. cmpr r1 # comparar ac & r1
  28. jmpg 16 # ac > r1 --> jmp 16
  29. jmp 6 # jmp 6
  30.  
  31. halt # stop

Código
  1. char codigo[] = {0x01, 17, 0x03, 0x00, 0x01,
  2.   25, 0x03, 0x01, 0x01, 0x00,
  3.   0x02, 0x01, 0x05, 0x03, 0x01,
  4.   0x02, 0x00, 0x04, 0x03, 0x00,
  5.   0x01, 0x01, 0x0B, 0x01, 0x0F,
  6.   28, 0x0C, 10, 0x00};

Código
  1. #========================================
  2. # CALCULAR MULTIPLICACION DE DOS NUMEROS
  3. #========================================
  4. # Utilizando 3 registros (incluso menos) se
  5. # pueden hacer funciones de multiplicación
  6. # de números.
  7. # resultado: r2.
  8. #========================================
  9.  
  10. # Inicialización de los datos
  11.  
  12. lit 10 # ac: 10
  13. store r0 # r0: 10
  14. lit 3 # ac: 3
  15. store r1 # r1: 3
  16. lit 0 # ac: 0
  17.  
  18.  
  19. # Bucles
  20.  
  21. load r1 # ac: r1
  22. dec # ac: ac--
  23. store r1 # r1: ac
  24. cmpl 0 # comparar ac & 0
  25. jmpe 23 # ac == 0 --> jmp 23
  26.  
  27. lit 10 # ac: 10
  28. store r0 # r0: 10
  29.  
  30. load r2 # ac: r2
  31. inc # ac: ac++
  32. store r2 # r2: ac
  33. load r0 # ac: r0
  34. dec # ac: ac--
  35. store r0 # r0: ac
  36. lit 0 # ac: 0
  37. cmpr r0 # comparar ac & r0
  38. jmpl 13 # ac < r0 --> jmp 13
  39. jmp 6 # jmp 6
  40.  
  41. lit 0 # ac: 0
  42. store r1 # r1: 0
  43.  
  44. halt # stop

Código
  1. char codigo[] = {0x01, 0x0A, 0x03, 0x00, 0x01,
  2.   0x03, 0x03, 0x01, 0x01, 0x00,  
  3.   0x02, 0x01, 0x05, 0x03, 0x01, 0x0A, 0x00,
  4.   0x0D, 0x29,
  5.   0x01, 0x0A, 0x03, 0x00, 0x02, 0x02, 0x04,
  6.   0x03, 0x02, 0x02, 0x00, 0x05, 0x03, 0x00,
  7.   0x01, 0x00, 0x0B, 0x00, 0x0D, 23, 0x0C,
  8.   10, 0x01, 0x00, 0x03, 0x01, 0x00};



Espero opiniones, críticas y sus comentarios
40  Programación / Programación C/C++ / Re: [Ayuda] Conversiones *char - int en: 17 Septiembre 2013, 22:07 pm
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.
Páginas: 1 2 3 [4] 5 6 7 8 9
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines