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


Tema destacado: Recuerda que debes registrarte en el foro para poder participar (preguntar y responder)


  Mostrar Mensajes
Páginas: 1 2 3 4 5 6 7 8 9 10 11 12 [13] 14 15 16 17 18 19 20 21 22 23 24 25
121  Programación / Programación C/C++ / Re: Duda con correspondencia entre arreglos y punteros en C++ en: 2 Junio 2020, 19:37 pm
Cierto, fue un resbalón escribit que primero se incrementa. Lo que quise decir es que, dada la precedencia de operadores, primero se evalúa la expresión dir_numeros++ (que, al tratarse de postincremento, nos da el valor actual de dir_numeros), esto se desreferencia, y después se incrementa el puntero.
122  Programación / Programación C/C++ / Re: Duda con correspondencia entre arreglos y punteros en C++ en: 2 Junio 2020, 18:59 pm
El operador ++ tiene mayor precedencia que el *, por lo que primero se incrementa el puntero y luego se "desreferencia". En cambio así:

Código
  1. (*dir_numeros)++

incrementas el valor.
123  Programación / Programación C/C++ / Re: Procesos con fork en: 23 Mayo 2020, 17:11 pm
A simple vista el error que veo es en el último proceso hijo. Siempre debes cerrar los descriptores que no usas en cada proceso, y en ese último no lo estás haciendo con los de fd. Eso debe estar provocando un bloqueo.

Además, el wait final lo estás usando incorrectamente. Deberías pasarle NULL como parámetro (o usar waitpid, si quieres especificar pids concretos, pero no lo veo necesario).
124  Programación / Programación C/C++ / Re: Dividir cadena en subcadena C++ en: 17 Mayo 2020, 20:53 pm
Me parece un poco ambiguo lo de cada vez que llegue a una 'a'. O sea, si la cadena no empieza con 'a', como en "xyzajndfvaorncak89s", ¿la primera subcadena debería ser xyz, o ajndfv? Como lo planteas parecería que es la primera, pero a mí me parece más lógica la segunda, así que me enfoco en ella.

Una opción es la función strtok, que ya te mencionaron, pero ten en cuenta que es para cadenas de C (arreglos o punteros char). Aunque hay forma de acceder al buffer interno de string, por varias razones podría no funcionar con strtork, además de que esta función es "destructiva"; es decir, modifica la cadena origen, por lo que al final tu string quedaría alterado. En todo caso, si quieres usar strtok, sería mejor crear una copia de tu string en un arreglo char, y trabajar sobre ella.

Una alternativa es usar las funciones miembro de string find() y substr(). Un ejemplo para encontrar la primera subcadena:

Código
  1. std::string::size_type inicio, fin = 0;
  2.  
  3. inicio = cadena.find('a', fin);
  4.  
  5. // Si se encontro una letra 'a'
  6. if (inicio != std::string::npos) {
  7.  fin = cadena.find('a', inicio + 1);
  8.  subcadena = cadena.substr(inicio, fin - inicio);
  9. }

Ya sólo te faltaría crear el programa y hacer un bucle basándote en esto.
125  Programación / Programación General / Re: ¿Por que segmentacion? en: 17 Mayo 2020, 16:55 pm
Si me permites otra pregunta, ¿cual fue la primera version de Windows y/o Linux que utilizo GDTs?

Bueno, considerando que las GDTs no existen en modo real, y que en el protegido no son opcionales (crear una y pasársela al procesador es requisito para siquiera iniciar este modo), la respuesta sería: la primera que corriera en este modo. En el caso de Linux, todas, desde la primera versión del kernel, lo han hecho. Con Windows no estoy seguro, pero probablemente la Windows/386. En esos tiempos Windows no era un sistema operativo, sino una interfaz gráfica encima de DOS, pero me parece que esa versión sí iniciaba el modo protegido al ejecutarse. Ya como SO propiamente dicho, todas sus versiones, NT o 9x, corrían en este modo, por lo que necesariamente usaban una GDT.
126  Programación / Programación General / Re: ¿Por que segmentacion? en: 14 Mayo 2020, 05:39 am
¿Hablas de modo real o protegido? Porque es muy diferente según el caso y veo que se están mezclando los dos.

En modo real las direcciones sí son de 20 bits y se calculan multiplicando el selector de segmento por 16 (que añade 4 bits 0) para formar una dirección base de 20 bits y a esto se le suma el offset para obtener la dirección efectiva.

En modo protegido, las direcciones son de 32 bits (quitando el 80286, en el cual son de 24 bits), y aunque se sigue usando un selector de segmento y un offset, el proceso de conversión es muy diferente. En este modo, existe una tabla global de descriptores de segmento. Cada uno de estos descriptores es una estructura de 64 bits con información acerca de un segmento, como su dirección de inicio, su dirección máxima válida (que sirve para calcular su tamaño), nivel de privilegio, permisos, etc. Entonces, cuando tenemos una dirección lógica, primero se toma el selector de segmento, que en este caso hace referencia a un descriptor dentro de la tabla global; después, de dicha tabla se obtiene la dirección base del segmento; luego se le suma el offset para obtener una dirección lineal. Si no se usa paginación, esta dirección ya se refiere directamente a una dirección física de memoria. En caso de que se use paginación (que, por cierto, sólo está admitida en modo protegido) se hace una conversión adicional, que varía según el tamaño de página usado. Y, porque quizás más adelante te surja esta duda, te comento que aunque en modo protegido se puede usar un modelo de memoria plano, la segmentación sigue estando presente. La ventaja es que todo esto se realiza de forma interna y, en general, transparente al programador. Es decir, usando modelo plano, te puedes olvidar de la segmentación, y escribir programas como si no existiera.

En cuanto a lo que preguntabas sobre la memoria de los procesos, únicamente en modo protegido se ofrece protección. Para eso se puede usar tanto la segmentación como la paginación. En el caso de la primera, una forma es mediante tablas de descriptores locales. Cada tarea tiene una propia, la cual contiene únicamente los segmentos válidos para ella (aparte de los de la tabla global, que son accesibles a las tareas, siempre que los niveles de privilegio lo permitan). Todo esto podría sonar muy ineficiente, pero el procesador tiene maneras de hacer que estas verificaciones se realicen lo más rápido posible, como registros que guardan información de la tabla global y de la tarea actual, entre otras cosas
127  Programación / ASM / Re: Declaracion de segmentos en TASM en: 8 Mayo 2020, 17:29 pm
Sé que no hay desperdicio; eso lo puse como ejemplo de una conclusión errónea a la que se podía llegar. Pero tienes razón, aquí yo estaba mezclando selectores de segmento con los segmentos que el ensamblador declara. Y es que hace demasiado tiempo que no toco nada de esto, y si ya de por sí el tema de la segmentación en x86 es complejo...


Código
  1. SEGMENT cseg 'code'
  2.  

Eso último entre comillas simples es el nombre de "clase". El ensamblador pone juntos en memoria los segmentos pertenecientes a una clase, independientemente del orden en que hayan sido declarados o si están en diferentes archivos. Hay algunos nombres predefinidos y "code" es uno de ellos. Ése es básicamente su uso.
128  Programación / ASM / Re: Declaracion de segmentos en TASM en: 7 Mayo 2020, 17:53 pm
Sí, aunque creo que puede ser bastante engañoso y confuso mezclar el segmento y su contenido.

Aquí estamos poniendo ejemplos sencillos para ilustrar ciertos conceptos, pero obviamente, en una situación mas realista, es incorrecto suponer que todos los segmentos van a coincidir. Antes de intentar hacer cualquier cosa con un dato, siempre tenemos que hacer apuntar DS (o ES y usar ASSUME o segment overrides) al segmento que lo contiene. Naturalmente, en el ejemplo anterior, a poco que se toque el código (por ejemplo, haciendo que seg2 sea más grande), el programa puede dar resultados incorrectos. Esto lo aclaro por si alguien que empieza lee esto. En los ejemplos que pondré a continuación, siempre supongo que DS apunta al segmento correcto.

Si tenemos esto:

Código
  1. SEGMENT seg2 WORD
  2. var1 DW ?
  3. ENDS seg2

y var1 está en 0910:0002, decir que seg2 también inicia en esa posición es, como decía al principio, engañoso. Siempre que hagamos referencia a seg2 en el código, el valor que se sustituirá será 0910, nada más. Luego, dando por sentado que hemos hecho, como deberíamos, que DS apunte a seg2, si queremos ver el offset de var, veremos que es 2. Pero si se supone que seg2 (el segmento declarado por TASM) inicia en 0910:0002, la pregunta que surgiría es ¿por qué el ensamblador desperdicia memoria metiendo ese hueco de 2 bytes? Más aún, y siguiendo con ese razonamiento, si seg2 inicia en 0910:0002, y var1 tiene un offset de 2, eso implicaría que la dirección de var1 es 0910:0004, lo cual es incorrecto. La realidad simplemente es que seg2 inicia en el segmento 0910 o, si se quiere, en 0910:0000 (no necesitamos offset, porque, por definición, siempre va a ser 0000) y se superpone con un segmento anterior, y de ahí que var1 se coloque en una posición más alejada, es decir, los datos que contiene, sí que inician en el offset 2. Por eso, como decía al principio, mezclar seg2 con sus datos que contiene puede ser útil como abstracción y para simplificar las cosas, pero es algo inexacto y cuando queremos profundizar un poco, la abstracción se rompe; de ahí que yo prefiera separar los conceptos.
129  Programación / ASM / Re: Declaracion de segmentos en TASM en: 7 Mayo 2020, 02:54 am
Los segmentos siempre están alineados a un párrafo. Lo que ponemos en CS, DS, etc. no son direcciones de memoria, sino números de segmento, y su dirección se calcula multiplicándolos por 16, (o desplazándolos 4 bits a la izquerda). Por ejemplo, cuando el valor de CS es 0x0020, la dirección real del segmento es 0x00200. Al especificar BYTE, WORD, etc. al definir un segmento, estamos indicando cómo queremos que esté alineada la dirección donde comienzan las instrucciones o datos contenidos en él, pero el segmento en sí siempre estará en dirección múltiplo de 16.

En el ejemplo que pusiste, vemos que ref fue colocado en la dirección 0x07100 (segmento 0x0710) y contiene un sólo byte, por lo que termina en 0x07101. Luego tienes seg1, con alineación WORD, por lo que se busca la primera dirección disponible que sea múltiplo de 2 (en este caso, 0x07102) y ahí se coloca su contenido. Todo esto hace que casi no se desperdicie memoria, pero ¿que pasa con seg1 en sí? Como 0x07102 no es múltiplo de 16, lo que se hace es tomar la dirección múltiplo de 16 inmediatamente anterior. En este ejemplo será 0x07100, lo cual hará que ref y seg1 estén en el mismo segmento "real", pero para que no se superpongan sus datos, el byte de seg1 no tendrá un offset de 0 sino de 2. Y lo mismo pasa con el resto de segmentos que pusiste. Así que esto que habías hecho era correcto:

Código
  1. MOV AX, ref
  2. MOV AX, seg1
  3. MOV AX, seg2

simplemente sucedió que los 3 segmentos, así como cseg, y por ende, CS, apuntaban a la misma dirección. Prueba a alinearlos todos con PARA y verás que AX tendrá valores distintos. O bien, déjalo como está, pero cambia el DB ? de ref por DB 15 DUP(?) y verás que debería quedar en un segmento distinto al resto.
130  Programación / Programación C/C++ / Re: ¿Alguna manera para guardar resultados de un for? en: 4 Mayo 2020, 19:38 pm
¿Cuál es la razón de usar una cadena? Usando array, vector, o manejo dinámico de memoria te evitas conversiones. Y si quieres imprimir los números por pantalla, en un bucle directamente muestras variable[ i ], y listo. Y nada impide que agregues un cout << "," si quieres separarlos. Si forzosamente quieres poder imprimirlos todos en una sola instrucción y por eso te gustó la idea de la cadena, te va a tomar algo de trabajo, porque el ejemplo de arriba con una cadena, en realidad no te sirve. La línea

Código
  1.    numeros += i;

no está metiendo en numeros los caracteres '0', '1', sino los valores numéricos 0, 1, etc., que no representan caracteres válidos (el 0, por ejemplo, es el nulo, o fin de cadena). Por lo tanto, numeros no es una cadena válida, y no vas a poder imprimirla directamente. La única ventaja que te aportaba el uso de string aquí se pierde, así que no hay razón para hacerlo.

Si aún así en verdad quieres usar una cadena, lo primero es que, como ya te recomendaron, tomes un manual y leas al menos lo básico de string y la STL en general. Aunque hay varias maneras de hacer las conversiones que quieres y no es difícil, no veo mucho sentido a ponerte código de eso, dado que, con poco que lo toques, seguramente te dará problemas y tendrás más dudas que al principio. La STL podrá tener ciertas ventajas, pero no es fácil ni amigable. De hecho, desde el punto de vista de la usabilidad, a muchos nos parece una atrocidad, aunque una vez que agarras un poco de experiencia no es tan mala.

Otra opción menos complicada podría ser la función strtok, pero tiene sus inconvenientes. Puedes buscarla en Google y ver si la quieres usar, pero insisto en que son más recomendables las otras alternativas. Y siempre puedes convertir los números a cadena (mucho más fácil que lo contrario) con la función to_string(). Por ejemplo, esto:

Código
  1. cadena += to_string(vec[i]);

convierte el valor del elemento i de un vector, en un string y lo añade al final de cadena. De esta manera tienes el vector para acceder a los valores individuales, y la cadena para imprimirlos en una sola instrucción (aunque reitero, no es nada difícil y sólo toma un par de líneas imprimir todos los elementos manualmente).
Páginas: 1 2 3 4 5 6 7 8 9 10 11 12 [13] 14 15 16 17 18 19 20 21 22 23 24 25
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines