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

 

 


Tema destacado: Tutorial básico de Quickjs


  Mostrar Mensajes
Páginas: 1 ... 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [22] 23
211  Programación / Programación General / Re: Fundamento del Ensamblaje y Linkeado de Programas en: 26 Abril 2020, 21:22 pm
Esta bien...

Hablamos entonces de referencias como -cualquier tipo de- objeto a ser localizado en el algoritmo.
Los pases son, en pocas palabras, un ordenamiento (en todo sentido) del proceso de compilacion.
y ¿como calcula el compilador el numero de pases que son necesarios, en ese caso (o cualquier otro)?
El codigo objeto es entonces mas bien informacion que codigo, que el enlazador utiliza para enlazar.

En la última fase (ya del linker) si quedare algo por hacer sería recorrer de nuevo el fichero resultante y actualizar las direcciones. El linker, se encarga además de procurrar todas las referencias externas, es decir aquellas llamadas que se harán a objetos fuera dle proyecto (librerías dll, controles d eusuario, etc...), pués deba añadir código ahí para resolver el tipo de llamada a dicha librería (algunas librerías utilizan la pila
Esto me genera un poco de confusion.
Entonces seria algo asi: el compilador se encarga del ordenamiento del algoritmo principal, en forma de "arbol" (digamos). Y el enlazador se encarga del ordenamiento de su interaccion con este exterior compuesto de librerias de enlace dinamico, librerias estaticas, etcetera. ¿no?
Y ¿es el compilador o el enlazador el que auna los algoritmos de un mismo proyecto? Por deduccion de lo anterior pensaria que es el compilador.

Uf. Cuanto necesitaba leer este articulo.
Me parece interesante que la ignorancia pueda ser una fuente de creatividad. Yo no conocia las maneras en las que se realiza esto y como consecuencia invente varias maneras de hacerlo. Me gustaria incluirlas aqui pero creo que seria demasiado off-topic. Pero va desde una locura de retornos en la pila, a simplemente el registro DX. En verdad la programacion (especialmente en ensamblador) puede convertirse en un lienzo en blanco pidiendo a gritos tu imaginacion.

Gracias por tu tiempo. Este foro es increible, en verdad  :o.
212  Programación / Programación General / Re: Fundamento del Ensamblaje y Linkeado de Programas en: 26 Abril 2020, 17:51 pm
En general no es sencillo compilar de una sola pasada, por varias razones.
Okay... entonces de aqui viene.

- Hay referencias que no se han resulto, se guardan datos intermedios y en otra fase se termina de verificar.
¿te refieres con esto a que en el proceso las direcciones varian y al mismo tiempo y por el mismo son ajustadas?

- El código es tan grande que la memoria no puede albergar todo el proyecto en memoria.
Los archivos COM, son de cuando los programas eran tan pequeñitos que cabían en un unico sector (no más de 64kb.). Eso implicaba que las direcciones podían ser consideradas absolutas, si se cargaban en un sector siendo la dirección absoluta real la dirección del sector + el desplazamiento en el sector. Eso mismo supone ciertas restricciones, a cambio de una carga más rápida (no hay que traducir las direcciones que ya tiene el COM).
Un exe, en cambio puede tener cualquier tamaño, y exige que durante la carga todas sus direcciones sean modificadas (una vez cargado en memoria), conforme al valor que contienen y al punto en memoria que fueron cargados... eso supone una cierta lentitud en la carga en memoria (el loader), a su vez se libera de ciertos rigores como el tamaño limitado o los saltos...
En fin, la diferencia básica se limita a la velocidad de carga que hoy es despreciable peroq ue en los 70-80 podría suponer una gran diferencia dada la velocidad de ejecución d elos procesadores de entonces.
Cuando la velocidad de los procesadores se disparó y el tamaño de la memoria siguió el mismo camino, los programas COM, básdicamente quedaron obsoletos (pués ya más que ventajas ofrecen restricciones)
Imagino que estamos hablando de la relacion entre la velocidad de acceso al disco y a la memoria.
Sin embargo, asi como un archivo COM es limitado por su estructura, ¿un EXE no debe ser igualmente no mayor al rango del registro de segmento de codigo? (Si vamos al caso)
 
Lo siento he tachado esa parte final, porque tú sabrás que 'cuestiones superficiales' conoces, yo no sé cuales son, y creo que nadie más que tú lo sepa... ni si son correctas o sesgadas, es asumir...sin conocimiento de causa.
Es decir, como dije cuando introduje mis preguntas, lo que tiene que decir Wikipedia (como antonomasia de las definiciones generales).

Me he tomado la molestia de buscar un hilo donde respondí varios temas a Yuki, luego abandonó el proyecto, así que ya no pude orientarle más...
He buscado el hilo, te pongo un link al mensaje específico que contesta por encima las fases de un compilador (típico). Aunque si estás interesado, te recomiendo leer todo el hilo:

https://foro.elhacker.net/foro_libre/escribiendo_un_compilador_en_vivo-t482796.0.html;msg2160676#msg2160676
De hecho me he preguntado varias veces como seria el codigo fuente de un compilador. Gracias por tu tiempo.

No suele haber tales referencias.
Y eso temia. En realidad es solo curiosidad.

 
Link es enlace, linking, es enlazar... Se trata de hacer que todos esos ficheros de código individuales sean uno solo, pero no se trata de eso solo, también (y sobretodo) se trata de otorgar las direcciones de memoria relativa dentro del código (el cargador del ejecutable durante la ejecución tomará las direcciones relativas y las transformará en direccioes absolutas en la memoria, aunque no es exactamente así...
¿Te refieres con esto, como pregunte antes, a que al momento de unir los archivos las direcciones varian y el enlazador debe encargarse de a su vez ajustarlas?

Ademas me pregunto si justamente a eso te refieres con lo que dices en seguida.

Gracias por responder.
213  Seguridad Informática / Criptografía / Re: El futuro de la criptografía en: 26 Abril 2020, 14:07 pm
A los sistemas critpograficos lo que pinturas han hecho los pintores. A pesar de las limitaciones para con las herramientas que se utilizan para emular matematicamente lo que se imagina como una forma de transformar informacion, lo unico que permanece omnipotente es la imaginacion. Para mi el critpoanalisis es fundamentalmente lo mismo que observar una pintura hasta ver las manos del pintor, y seguira siendo asi hasta que pueda expresarse (de la misma forma) el azar en una ecuacion.
214  Programación / Programación General / Fundamento del Ensamblaje y Linkeado de Programas en: 25 Abril 2020, 22:14 pm
Hola.
Echandole un vistazo a lo que tiene que decir Wikipedia acerca de esto me han quedado ciertas dudas acerca del funcionamiento, digamos, de bajo nivel del ensamblaje y linkeado de programas, en terminos generales.

¿Que es, fundamentalmente, la generacion del codigo objeto?
Facilmente en Internet puede encontrarse una variedad considerable de referencia para con este tema sin embargo lo que mas bien me pregunto es cual es el proceso preciso del compilador, tomando en cuenta que ya conozco las cuestiones mas superficiales. En verdad no pido (aunque agradeceria por añadidura) una explicacion (mas bien, resumen) de este proceso porque se que no merece un resumen. Tambien agradeceria saber en donde podria encontrar una buena referencia acerca del formato de archivo OBJ.

y, de igual manera, ¿que es, fundamentalmente, el proceso de linking?
Sin bastante que añadir, tengo basicamente la misma duda.

Como resultado de estas cuesitones, ademas tengo algunas otras preguntas:
Ya que no conozco el funcionamiento basico del proceso de linking, pido que disculpen mi ignorancia porque realmente no se si es posible linkear (¿soy el unico al que le parecen raros estos anglicismos?) un archivo COM pero, si es asi, ¿cual es la diferencia entre linkear un archivo COM y un archivo EXE? y ¿en que afecta este proceso los valores de los registros de segmento, o a los mismos en definitiva, en tiempo de ejecucion?

Gracias de antemano y saludos.
215  Programación / Programación C/C++ / Re: Llamada a una funcion en un esquema de memoria segmentada en: 25 Abril 2020, 18:13 pm
¿Qué ensamblador usas?

He utilizado dos hasta ahora: un ensamblador de un emulador del i8086 (con el cual hago los COM) y ahora, por la recomendacion de Flat Assembler, utilizo el mismo. El primero si que codifica el segmento en el parametro para la instruccion sin embargo no la instruccion como far, sino siempre como short (a menos que la especifique far, lo cual no permite entonces especificar un segmento y, a su vez, lo mismo que me tiene las orejas calientes); y el segundo no permite especificar de esa manera el segmento en definitiva.

Código
  1. dwoldISR dd ?

eso automáticamente hará far a la llamada.

Seria una cuestion de utilizar MASM o TASM. Tengo TASM para 32-bits y como es de esperarse no encontre una manera de que compile codigo para 16-bits.


Edito: acabo de descargar TASM 5 y codifica perfectamente esta instruccion y, como dijiste, deduce el tipo de llamada por el tipo de dato. Yo honestamente me sentia un poco esceptico respecto a la definicion de tipo de dato en ensamblador. Por supuesto ahora entiendo (como era evidente) que cada ensamblador tiene sus "cosillas"

Posdata: En verdad fue una buena idea hacer esta pregunta, ahora veo lo perdido que estaba. Gracias por ser parte de la linterna.


¿No será que tu ensamblador usa alguna sintaxis distinta para anteponer el registro de segmento? Me parecería extraño que simplemente no admitiera eso.

De esto sinceramente no estoy seguro, seria una cuestion de estudiarlo mejor. Sin embargo honestamente no veo muy probable que exista una manera si no es simplemente con esa nomenclatura tan (digamos) estandar.

No me viene a la mente ninguna referencia que trate expresamente sobre interrupciones. La mayoría de los libros de ensamblador trataban el tema, aunque casi siempre de forma algo superficial. Creo que esto yo lo aprendí sobre todo de algún manual viejo de Intel, pero no lo recuerdo en este momento. Si me acuerdo de algo, lo posteo.

Esta bien, muchas gracias.
216  Programación / Programación C/C++ / Re: Llamada a una funcion en un esquema de memoria segmentada en: 23 Abril 2020, 20:35 pm
¿Hiciste que DS apunte al segmento donde se encuentra dwoldISR (que, si estamos en un .COM, normalmente sería CS)? Porque como sabrás, dentro de un manejador de interrupciones no hay forma de saber de antemano los valores de los registros de segmento, salvo CS, naturalmente, así que, o apuntas a DS al segmento correcto o, más simple, agregas un override con CS:

Código
  1. call cs:dwoldISR

Acabo de darme cuenta de esto. Si lo sabia, sin embargo lo pase por alto, como dije me considero un novato interactuando con estos mecanismos. Gracias por tu ayuda, ahora funciona correctamente.

Aunque para que funcionase tuve que especificar la direccion de la llamada de manera explicita:

Código:
pushf
call far 0b7fh:1923h ; esta es la direccion del servicio de interrupcion 9 en DOS 6.22
iret

Ya que ningun ensamblador me codifica instrucciones del tipo:

Citar
call <registro de segmento>:<referencia a memoria>
(como, por ejemplo, call cs:dwoldISR)

Ademas, ¿no seria fundamentalmente el mismo problema?, es decir, igualmente, ¿no habrian de ser diferentes, al momento de ejecutarse la interrupcion, los valores de los segmentos, haciendo imposible hacer referencia a la direccion (lineal) que es correcta?


Edito: No tome en cuenta que el registro CS se modifica cuando ocurre una interrupcion al decir esto. Pido obviar esta pregunta.


Por cierto, ¿conoces alguna referencia acerca de la programacion de interrupciones? Aunque conozco la manera en la que funcionan, creo que me hace falta algo de informacion practica respecto a ello.
Saludos.
217  Programación / Programación C/C++ / Re: Llamada a una funcion en un esquema de memoria segmentada en: 21 Abril 2020, 13:51 pm
Pasa que los COM están muy limitados y una de las pocas razones para usarlos era su simpleza, que era lo que quise decir arriba, cuando comenté que los punteros far eran más simples que los near (en realidad me quería referir a los COM y los EXE, pero entre que borraba y cambiaba mi mensaje, se me quedó mezclado). Obviamente, tanto como más simples no, es sólo que incluyen el segmento y no va implícito CS, como en los far. Como sea, lo que sucede con los COM es que al ejecutarlos, se cargan en memoria tal cual están en el disco, todo en un sólo segmento, y sin las reubicaciones que tienen lugar con los EXE. Esto hacía que, entre otras cosas, fuera mucho más rápido cargar los COM, pero con desventajas, como el tener sólo un segmento. Sin embargo, no es tan simple, ya que, como había comentado antes, sí que hay formas de acceder a datos más allá, pues nada impide que cargues valores en DS ó ES, por ejemplo, pero obviamente no se puede modificar directamente a CS.

Sin embargo como comentas en seguida es posible mientras no se trate de codigo reubicable. La parte de mi programa que ejecuta esta llamada es una llamada a un ISR sin la utilizacion de la instruccion INT. Es decir, especificando de manera explicita el segmento y el desplazamiento para con el ISR. Al tener problemas con este tipo de llamadas y la codificacion de llamadas far, se me ocurrio lo siguiente:

Código:
;pushf en el caso de una llamada a ISR
push cs
push delta
push es ;segmento para con la llamada
push bx ;desplazamiento para con la misma
retf ;ultimamente resulta en lo mismo que un CALL far
delta:

Me di cuenta de que a pesar de los problemas con la instruccion CALL tipo far, los ensambladores codifican perfectamente este pequeño algoritmo (que incluye precisamente un retorno de igualmente tipo far, y funciona de maravilla).

Hace ya mucho que no programo nada en 16 bits y puede que se me escape algún detalle o me confunda en algún punto, pero en esencia así es como funciona:

Como bien intuyes, no es que el sistema operativo impida a estos archivos hacer llamadas far durante la ejecución, sino que, como normalmente éstas implican código reubicable, los linkers se quejan y no permiten generar archivos COM. Podrías intentar forzar esto usando un "truco" muy común, que es meter tú mismo los opcodes de la operación. Por ejemplo, en la parte de tu código donde quieras la llamada, usas un DB con el valor del opcode para la llamada far deseada, e inmediatamente después un par de DW con los valores de segmento y desplazamiento, si los sabes.

Dicho todo lo anterior, y respondiendo a tu última pregunta, los EXE no tienen ninguna de estas limitaciones, así que te recomiendo que no te compliques con los COM. De esta manera, puedes hacerlo desde C, y en este caso, el compilador sí que debería hacer lo que pides. E independientemente del compilador que uses, si permite generar COM, obviamente debe poder hacer EXE de 16 bits.

Lo intente de esta manera y me di cuenta de que la raiz de mi problema no yace en la llamada far sino en el codigo. Igualmente gracias por ayudarme a aclarar tantas cuestiones sobre estas llamadas, el esfuerzo de ninguna equivocacion se pierde.

El programa que estoy intentando hacer es simplemente un TSR que engancha (hook) un ISR de la BIOS a una parte del mismo. Todo funciona perfectamente hasta que retoco (tweak) el slot del ISR (el cual es la interrupcion general del teclado en la BIOS, es decir, la 09h). Desde ese momento el sistema parece dejar de reaccionar. Este es el codigo al que se "hookea" el ISR:

Código:
pushf
call far dwoldISR
iret

En dwoldISR esta almacenada la direccion original de la rutina de servicio.

En verdad no se cual es el problema realmente. Igual sera una cuestion de que siga intentandolo.
Me parecio de mala educacion hablarte del problema sin la raiz del mismo.

Aprecio tu ayuda y tu tiempo.
Saludos.
218  Programación / Programación C/C++ / Re: Llamada a una funcion en un esquema de memoria segmentada en: 18 Abril 2020, 21:12 pm
A diferencia de los punteros near, los far son más simples: los 2 bytes más significativos contienen el segmento, y los 2 menos significativos el desplazamiento. Las operaciones que hago en el código que puse son simplemente extraer los el conjunto de dos bytes que interesen, para obtener sus componentes; o bien, juntarlos en un único número de 4 bytes, para generar el puntero far.

Esto lo sabia, sin embargo digamos que no dispongo aun del conocimiento intuitivo para no cometer ciertos errores. Sinceramente llevo apenas un mes utilizando tanto C como ensamblador para esta forma de programacion (me refiero a la interaccion directa con los mecanismos del procesador).


Bueno, en realidad no estoy haciendo una rotación (de hecho, C no proporciona operadores para eso) sino un simple desplazamiento a la derecha. Con esto, como decía arriba, obtengo el valor los 2 bytes más significativos. Multiplicar por 0x10 daría un resultado completamente diferente. La operación a nivel de bits equivalente a esa muliplicación sería (puntero_far << 4). La operación aritmética equivalente al desplazamiento que hago sería dividir entre 0x10000 (65536). De cualquier forma, las operaciones a nivel de bits, además de que suelen ser más eficientes que las aritméticas, en estos casos me parece que hacen más explícito lo que se quiere hacer.

Me has generado y resuelto una duda en el mismo instante. No estaba seguro de si el operador de desplazamiento era precisamente de desplazamiento y no ademas de rotacion (circular). Digamosle una confusion de terminos inadvertida.  :silbar:
Ademas he cometido un error idealizando la direccion efectiva como una combinacion de dos bytes y no de dos words, por eso mi confusion con el desplazamiento de los 16 bits: si la direccion estuviese compuesta de 8 bits para el selector de segmento y 8 bits para el desplazamiento (como la idealizaba), entonces hacer un desplazamiento de 16 bits no tuviese sentido. Mi error.


Pasé por alto un mensaje anterior. ¿Esás generando un archivo COM? Porque si es así, a eso se debe el error. Los COM no pueden hacer llamadas far, dado que están limitados a un sólo segmento. Aunque sí que hay forma de acceder a datos en otros segmentos (teniendo que calcularlos manualmente, y directamente en ensamblador, no en C), no es así con las llamadas far. Lo normal sería que el linker diera error, diciendo que el archivo contiene referencias reubicables (relocatable), pero es posible que algunos simplemente conviertan las llamadas far a near, o directamente ignoren el problema y las dejen far, lo cual ocasionará que el programa falle durante la ejecución.

Si, el archivo es un COM. Esto no lo sabia. El codigo que hago es para una maquina con DOS, y crei que el sistema ejecutaba las instrucciones como si codigo del kernel se tratase. Aunque en ausencia de modos de ejecucion no comprendo como es posible. ¿sabes como funciona esto precisamente, o en donde podria encontrar una referencia acerca de ello?
Ademas, si no es molestia, ¿existe entonces una forma de ejecutable que el sistema si permita tales cosas? espero no parezca tonta la pregunta y delante solo tenga como respuesta controladores.
219  Programación / Programación C/C++ / Re: Llamada a una funcion en un esquema de memoria segmentada en: 17 Abril 2020, 13:28 pm
No sé si entendí bien lo que quieres, pero si ya tienes el puntero far y necesitas el offset y el segmento, lo puedes hacer así:

Código
  1. unsigned int segmento = (unsigned int)((unsigned long)puntero_far >> 16);
  2. unsigned int offset = (unsigned int)((unsigned long)puntero_far & 0xFFFF);

Lo intente, sin embargo parece que el compilador continua ignorando la diferencia entre un puntero comun y uno far. Creo que deberia tomar el consejo de analizar el codigo ejecutable resultante para comprender mejor como trata el compilador de Open Watcom este tipo de declaraciones. Es una lastima no encontrar mucha referencia sobre esta forma de referencia a memoria en internet, o al menos eso me parece.
Por cierto, si me permites la curiosidad ¿por que en vez de hacer una rotacion de 16 bits (puntero_far >> 16) no multiplicar simplemente el segmento por 0x10?


Si lo quieres es lo opuesto:

Código
  1. puntero_far = (void far (*)(int))(((unsigned long)segmento << 16) + offset);

Como los tamaños de los tipos varían de un compilador a otro, puede que necesites cambiar long por algún otro tipo que ocupe 32 bits, y poner __far en lugar de far.

En cuanto a tu pregunta original, C no tiene concepto de punteros near, far, modelos de memoria, ni nada por el estilo, por lo que todo esto depende totalmente del compilador. Lo más cercano a Open Watcom que usé es el Watcom C normal, pero hace mucho de eso, y además no sé qué tanto difieran, pero el código que pones tendría que funcionar. En general, usar la palabra "far" (o __far, o cualquier otro equivalente en el compilador que se use) ya debería bastar para llamar a estas funciones. No sé cuál sea el problema aquí, pero yo vería si el Open Watcom no hace algo "raro" al usar __far. Lo mejor en estos casos es checar el ensamblador generado por el compilador, ya sea mediante algún flag, si lo tiene, o desensamblando el ejecutable.

Encontre una referencia de Wikipedia con esta manera de tratar este tipo de puntero sin embargo sigo pensando que debe haber algo mal con la forma de tratarlos por parte de este compilador, espero no sea una supersticion, jajaja.

Saludos, gracias por tu ayuda.
220  Programación / Programación C/C++ / Re: Llamada a una funcion en un esquema de memoria segmentada en: 14 Abril 2020, 21:00 pm
En respuesta a @XSStringManolo,

Si, de hecho precisamente es lo que hago para probar el funcionamiento. Sin embargo me refiero mas bien a la codificacion de las instrucciones.
Pense en buscar la referencia de Intel de la instruccion CALL pero tendria que hacer el trabajo del compilador y honestamente me parece demasiado tedioso.
Para introducir mejor mi problema, hare un ejemplo:

Para hacer una llamada a una funcion del segmento CS, el mnemonico (si me permites un anglicismo) CALL puede expresarse simplemente:

 
Citar
CALL mylabel

En cambio para hacer una llamada fuera del segmento en real-mode seria expresado:

Citar
CALL ES:lo_que_sea

En donde lo_que_sea hace referencia un registro, direccion de memoria, ... (vamos, Intel).

Mi problema es que la codificacion de esta instruccion en C por parte de un compilador, de manera estandar, es:

Citar
CALL 0xXXXX
(notar que seguimos en el contexto de 16 bits)

Ahora mi pregunta es: tomando en cuenta esto, ¿como se expresa una llamada fuera del segmento?

Por ejemplo, si en un sistema DOS, ya que lo mencionas, tengo un programa con la funcion getivt (BYTE, WORD*, WORD*) la cual almacena en sus ultimos argumentos el segmento de la entrada del slot del vector de interrupcion (del sistema MS-DOS) y el offset respectivo, especificado por su primer argumento, y tengo el siguiente codigo:

Código
  1. WORD segmentselector, offset;
  2. void __far (*interrupt21h)(); /* __far para precisar una funcion fuera del segmento por defecto. Sin embargo incluso asi el compiador parece ignorar esta especificacion */
  3. getivt (0x21, &segmentselector, &offset);
  4.  
  5. /* aqui comienza mi confusion */
  6.  

la pregunta precisa seria: ¿como almaceno segmentselector y offset en el puntero, para realizar la llamada far?



Por curiosidad... que compilador de C te genera un .COM para 16 bits? ( Asumo que generas un .COM, no lo sé)

Open Watcom. Un proyecto para con un compilador bastante interesante.
http://wiki.openwatcom.org/index.php/Main_Page


Con Flat  Assembler puede generar código para 16 bits.

https://flatassembler.net/


Incluso puede que tu respuesta la encuentres aquí.

https://board.flatassembler.net/topic.php?t=11055

En verdad parece precisamente lo que buscaba. Muchas gracias por tu ayuda.
Saludos.
Páginas: 1 ... 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [22] 23
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines