Llamada a una funcion en un esquema de memoria segmentada

Iniciado por Usuario887, 14 Abril 2020, 18:32 PM

0 Miembros y 2 Visitantes están viendo este tema.

RayR

Probablemente ya sepas esto, pero dado que es un error muy común al trabajar con interrupciones, creo que no está de más preguntar. Antes de este código:

Código (asm) [Seleccionar]
pushf
call far dwoldISR
iret


¿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



Usuario887

#11
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.

RayR

¿Qué ensamblador usas? Porque aunque algunos son bastante especiales y no muy inteligentes (de ahí lo que te comenté de meter opcodes directamente, que es casi a prueba de fallos), tanto TASM como MASM admiten perfectamente llamadas así: call cs:dwoldISR. Sin embargo, debes omitir la palabra far, o no la aceptarán. De cualquier forma, es redundante, ya que el ensamblador lo deduce del operando. Si declaraste dwoldISR como palaba doble:

Código (asm) [Seleccionar]
dwoldISR dd ?

eso automáticamente hará far a la llamada.

¿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.

Lo malo de codificar directamente direcciones como en el código que pones, es que pueden variar, por ejemplo, entre versiones de DOS o diferentes BIOS. Es posible usar la técnica de meter opcodes y ahí poner la dirección de tu variable dwoldISR, y eso funcionaría bien, pero tendrías que calcular offsets, además de saber los tamaños de cada instrucción, etc. y realmente creo que no vale la pena, sobre todo porque al menos los principales ensambladores admiten las llamadas directamente.

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.

Usuario887

#13
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.