Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Usuario887

#421
Cita de: RayR en 24 Abril 2020, 18:30 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.

Cita de: RayR en 24 Abril 2020, 18:30 PM
Código (asm) [Seleccionar]
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.



Cita de: RayR en 24 Abril 2020, 18:30 PM
¿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.

Cita de: RayR en 24 Abril 2020, 18:30 PM
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.
#422
Cita de: RayR en 21 Abril 2020, 21:24 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 (asm) [Seleccionar]

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:


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.
#423
Cita de: RayR en 19 Abril 2020, 00:19 AM
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:


;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).

Cita de: RayR en 19 Abril 2020, 00:19 AM
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:


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.
#424
Cita de: RayR en 17 Abril 2020, 17:46 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).

Cita de: RayR en 17 Abril 2020, 17:46 PM
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.

Cita de: RayR en 17 Abril 2020, 17:46 PM
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.
#425
Cita de: RayR en 15 Abril 2020, 00:59 AM
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í:

unsigned int segmento = (unsigned int)((unsigned long)puntero_far >> 16);
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?

Cita de: RayR en 15 Abril 2020, 00:59 AM

Si lo quieres es lo opuesto:

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.
#426
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:


WORD segmentselector, offset;
void __far (*interrupt21h)(); /* __far para precisar una funcion fuera del segmento por defecto. Sin embargo incluso asi el compiador parece ignorar esta especificacion */
getivt (0x21, &segmentselector, &offset);

/* aqui comienza mi confusion */


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




Cita de: fary en 14 Abril 2020, 20:26 PM
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

Cita de: fary en 14 Abril 2020, 20:26 PM

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.
#427
Hola.

Soy nuevo en este foro y me gustaria hacer una pregunta.
He estado intentando desde hace una semana esto y sinceramente me frustra no hallar la manera. Lo que estoy intentando es hacer una llamada a una funcion que esta fuera del segmento por defecto (en modo real, es decir, real-mode tipo 8086), es decir, lejana (o far), desde el lenguaje de programacion C y no logro hacerlo. He utilizado ensamblador integrado (lo cual el compilador codifica como una llamada near, y me refiero a instrucciones tipo call es:[bx], por ejemplo), una locura de conversiones de tipos de punteros a funciones y hasta he intentado hacer el programa en su totalidad en emsablador como resultado de mi frustracion pero he terminado peor al haberlo "terminado" sin encontrar un ensamblador para 16 bits. ¿a alguien se le ocurre alguna solucion a mi problema?

posdata: Si alguien sabe de un ensablador para 16 bits (tipo TASM preferiblemente), se lo agradeceria.

Muchas gracias de antemano.