Autor
|
Tema: Declaracion de segmentos en TASM (Leído 10,447 veces)
|
RayR
Desconectado
Mensajes: 243
|
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: MOV AX, ref MOV AX, seg1 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.
|
|
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.966
Israel nunca torturó niños, ni lo volverá a hacer.
|
Cierto, aunque es necesario contar tanto con el selector de segmento como con el desplazamiento (offset) para para obtener una direccion segmentada con la que poder trabajar.
The segment address is always added to a 16-bit offset in the instruction to yield a linear address, which is the same as physical address in this mode. For instance, the segmented address 06EFh:1234h (here the suffix "h" means hexadecimal) has a segment selector of 06EFh, representing a segment address of 06EF0h, to which the offset is added, yielding the linear address 06EF0h + 1234h = 08124h. Because of the way the segment address and offset are added, a single linear address can be mapped to up to 212 = 4096 distinct segment:offset pairs. For example, the linear address 08124h can have the segmented addresses 06EFh:1234h, 0812h:0004h, 0000h:8124h, etc. https://en.wikipedia.org/wiki/X86_memory_segmentation
Volviendo al ejemplo original los segmentos declarados por TASM arrancan en (entre otras direcciones segmentadas): ref 0710h:0000h seg 0710h:0002h seg2 0710h:0004h cseg 0710h:0006h Poner el selector de segmento en AX no es suficiente para acceder a los datos (AX no sirve como indice tampoco), ni saber donde arranca el segmento declarado en TASM. Para poder acceder a los datos con los segmentos declarados en mi ejemplo: entry: mov bx, offset seg2 mov al, byte ptr [bx] ;esto no lee de 0:[bx] o [bx]:0, lee de ds:[bx] es decir ds:[0x8] mov al, byte ptr cs:[bx] ;cs:[bx] es decir cs:[0x8] es 0x66 mov al, byte ptr cs:[2] ;es 0x3 mov bx, seg1 mov ds, bx ;ponemos en dx el selector de segmento mov bx, offset seg1 ;ponemos en bx el desplazamiento mov al, byte ptr [bx + 1] ;ds:[0x5] es 0x5 mov al, byte ptr [bx + 2] ;ds:[0x6] es 0x7
Si le damos nombre a nuestros datos como por ejemplo cambiando uno por despues podemos acceder a los mismos: var db 7 ... entry: mov bx, seg1 mov ds, bx mov bx, offset var mov al, byte ptr [bx] ;ds:[0x6] es 0x7
|
|
« Última modificación: 7 Mayo 2020, 12:56 pm por Eternal Idol »
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
RayR
Desconectado
Mensajes: 243
|
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: SEGMENT seg2 WORD var1 DW ? 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.
|
|
« Última modificación: 7 Mayo 2020, 17:57 pm por RayR »
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.966
Israel nunca torturó niños, ni lo volverá a hacer.
|
¿Que es un segmento sin su contenido? ¿Un rango de memoria? Separar un segmento de sus datos no tiene sentido, un segmento es un bloque de memoria, un conjunto de bytes alineado a un parrafo y esos bytes que son sus datos tienen valores. Sin ir mas lejos al declarar un segmento en TASM nos permite darle valor a su contenido. "The segment alignment attribute tells the linker to ensure that a segment begins on a specified boundary. This is important because data can be loaded faster on the 80x86 processors if it's properly aligned." De la misma manera equiparar los segmentos de memoria y los segmentos declarados por TASM me parece errado como concepto y por lo explicado en este mismo hilo es imposible que sean exactamente lo mismo. Si seg2 es 0x910 y antes esta seg1 que es 0x910 quiere decir que seg2 no inicia en la misma posicion, por pura logica; es cierto que el segmento de memoria 0x910 siempre inicia en la misma direccion pero si podemos tener 3 segmentos declarados por TASM que inician en un mismo selector de segmento no podemos seguir diciendo que son lo mismo que los segmentos de memoria. Hacer referencia a seg2 en el codigo es solo una parte - inconclusa - del trabajo necesario para acceder a los datos que el segmento declarado por TASM contiene, se necesita tambien un desplazamiento, el cual tambien se puede conseguir haciendo referencia al mismo seg2 con offset. No se desperdicia nada, si inicia el segmento TASM con un offset de 2 bytes es que hay otro segmento TASM anteriormente ocupando 1 o 2 bytes (lo cual lo hace intrinsicamente diferente a un segmento de memoria que solo puede iniciar alineado a un parrafo). No es como lo planteas, offset de seg2 y offset de var1 son lo mismo, no hay nada que ocupe otros 2 bytes entre medias, el primer elemento de ese segmento no inicia en otro lugar que no sea el principio del mismo. Es cierto que offset es con respecto al segmento de memoria, es la unica forma de que funcione. Si seg2 iniciara en 0910:000 siempre entonces offset daria siempre 0 para un segmento declarado por TASM y no es el caso, devuelve el desplazamiento necesario para poder hacer estos segmentos de TASM funcionales. SEGMENT seg1 WORD var db 7 var2 db 8 ENDS seg1 SEGMENT seg2 WORD var1 DW 666h ENDS seg2 SEGMENT cseg WORD entry: mov ax, seg1 mov ax, seg2 mov ax, offset seg1 ;0x0 mov ax, offset seg2 ;0x2 mov ax, offset var1 ;0x2
|
|
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
Usuario887
Desconectado
Mensajes: 310
|
Nada mejor que probar para averiguar.
Si, en verdad. Gracias por tu ayuda.
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.
Me alegra que comentes esto porque supuse que a algo parecido tenia que referirse el manual con aligned. Y ¿se especifica de esta manera para que el direccionamiento comienze en la proxima direccion, o mas precisamente para que la forma de acceso por defecto al segmento sea BYTE, WORD, etc.? se busca la primera dirección disponible que sea múltiplo de 2
Esto como una implicacion de lo anterior, ¿no?. para que no se superpongan sus datos, el byte de seg1 no tendrá un offset de 0 sino de 2.
¿Y como el procesador deduce este offset al momento de acceder al segmento? ¿O debe ser especificado explicitamente en el programa?. Gracias por la ayuda. es necesario contar tanto con el selector de segmento como con el desplazamiento (offset) para para obtener una direccion segmentada con la que poder trabajar.
The segment address is always added to a 16-bit offset in the instruction to yield a linear address, which is the same as physical address in this mode. For instance, the segmented address 06EFh:1234h (here the suffix "h" means hexadecimal) has a segment selector of 06EFh, representing a segment address of 06EF0h, to which the offset is added, yielding the linear address 06EF0h + 1234h = 08124h. Because of the way the segment address and offset are added, a single linear address can be mapped to up to 212 = 4096 distinct segment:offset pairs. For example, the linear address 08124h can have the segmented addresses 06EFh:1234h, 0812h:0004h, 0000h:8124h, etc. https://en.wikipedia.org/wiki/X86_memory_segmentation
Esto responde mi pregunta. Ahora solo me pregunto que quiere decir 'code' en esa expresion. Sin embargo probablemente consiga la respuesta en seguida en el manual de TASM 5. Respecto a lo que comentas, Eternal Idol, acerca de ello, no estoy seguro... claramente tiene que ver con codigo pero me pregunto mas bien como es precisamente esta relacion. Ya que, si en vez de 'code', lo expresas asi: SEGMENT cseg 'code'
Resulta en lo mismo que: SEGMENT cseg 'qiwnef' ;(una cadena random)
Esto concluye claramente en la poca importancia de ello, sin embargo me sigue intrigando. Saludos.
|
|
« Última modificación: 8 Mayo 2020, 15:37 pm por marax »
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.966
Israel nunca torturó niños, ni lo volverá a hacer.
|
"The segment alignment attribute tells the linker to ensure that a segment begins on a specified boundary."
En este punto el manual es explicito (y tambien habla de la generacion de segmentos, los segmentos de memoria son pre-existentes al programa), el alineamiento le dice al enlazador que se asegure que un segmento comienza en un limite especifico, este puede ser en bytes: 1, 2, 4, 16, 256 y 4096.
En la practica podemos ver como eso sucede con los ejemplos ya publicados, y no estamos hablando de segmentos superpuestos, estos no inician en la misma direccion de memoria segmentada (de hacerlo hablariamos siempre del mismo segmento de memoria, parrafo X, direccion de memoria lineal X con igual o diferente tamaño, el cual el procesador desconoce), solo puede haber segmentos superpuestos cuando involucramos un selector de segmento + un desplazamiento - el ejemplo seria 0710h:0006h y 0709h:0076h ambas direcciones segmentadas apuntan al mismo lugar con dos segmentos diferentes - de otra manera tratamos exclusivamente con valores consecutivos de 0 a 0xFFFF. Aca hablamos de varios segmentos de TASM contenidos en un solo segmento de memoria por la forma de declararlos.
No se puede acceder de ninguna manera a 256 o 4096 bytes atomicamente (en modo real creo que a 16 tampoco, sinceramente esto me esta haciendo releer material precambrico), el alineamiento - que por defecto es 16 en TASM - no tiene que ver con eso.
El procesador no sabe nada de estos segmentos declarados en TASM, MS-DOS despues de cargar el ejecutable solo sabe que tiene que hacer relocalizaciones y gracias.
SEGMENT cseg 'lalala' << le dice a TASM genera un segmento de codigo (cseg) llamado lalala, esto (el nombre) no se ve reflejado en el binario, en el manual hay una muy breve explicacion.
|
|
« Última modificación: 8 Mayo 2020, 16:41 pm por Eternal Idol »
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
RayR
Desconectado
Mensajes: 243
|
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... 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.
|
|
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.966
Israel nunca torturó niños, ni lo volverá a hacer.
|
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... Yo ya lo habia olvidado por completo, por suerte, pero al menos ahora tengo en la mente mas razones para agradecer estar trabajando con un modelo de memoria plano
|
|
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
Usuario887
Desconectado
Mensajes: 310
|
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.
Lo intuia... aunque me considero demasiado poco experto aun para permitirme confiar en mi intuicion. Gracias, ahora comprendo la expresion correctamente. por suerte
Me parece demasiado arriesgado hablar de suerte y de ensamblador en el mismo contexto... Saludos.
|
|
« Última modificación: 9 Mayo 2020, 17:18 pm por marax »
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.966
Israel nunca torturó niños, ni lo volverá a hacer.
|
Me parece demasiado arriesgado hablar de suerte y de ensamblador en el mismo contexto... ¿Cual seria el riesgo exactamente? ¿Tener que lidiar con codigo de los años 80s/90s? Las probabilidades de que tenga la necesidad (el foro no cuenta, hablo profesionalmente) de depurar ( debug.com/.exe desaparecio de mi SO hace rato largo cuando aparecieron a su vez los procesadores de 64 bits) y/o programar en ensamblador x86 de 16 bits son infimas por no decir nulas y ya lo eran incluso la decada pasada.
|
|
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
<<<<<TASM - AYUDA>>>>> Pls...
Ingeniería Inversa
|
Amerikano|Cls
|
1
|
4,163
|
20 Septiembre 2007, 20:05 pm
por byebye
|
|
|
no me sale un exe. al compilar con tasm
ASM
|
javier210186
|
4
|
5,295
|
8 Diciembre 2009, 00:40 am
por javier210186
|
|
|
como instalar tasm
ASM
|
karmi
|
1
|
5,693
|
4 Febrero 2011, 00:34 am
por Garfield07
|
|
|
TASM Suma de numeros
ASM
|
lexoazul
|
4
|
11,590
|
12 Marzo 2012, 14:03 pm
por lexoazul
|
|
|
Ayuda suma en TASM
ASM
|
BetoRoGa
|
1
|
4,347
|
18 Octubre 2015, 06:31 am
por Eternal Idol
|
|