Pregunta

Estoy trabajando en un programa de montaje para un microcontrolador basado en ARM Cortex-M3 (conjunto de instrucciones Thumb 2), utilizando como GNU.

En un código de ejemplo que encuentro directivas como .size, .section y .type que entiendo que son directivas ELF. Como un ejemplo:

    .section    .text.Reset_Handler
    .weak       Reset_Handler
    .type       Reset_Handler, %function  
Reset_Handler:
    bl      main
    b       Infinite_Loop    
    .size   Reset_Handler, .-Reset_Handler



Se dice que la directiva .type para establecer el tipo de un símbolo - por lo general, ya sea a% objeto (? Significado de datos) o la función%. No sé qué diferencia hace. No siempre se incluye, por lo que no estoy seguro cuando se van a utilizar.

También en relación con esto es la directiva .thumb_func. De lo que he leído parece que podría será equivalente a:

.thumb 
.type Symbol_Name, %function

O es algo completamente diferente?



.size supuestamente establece el tamaño asociado con un símbolo. Cuando esto es necesario, no tengo ni idea. Se calcula esta por defecto, pero overrideable con esta directiva? Si es así - cuando usted desee anular?



.section es más fácil de encontrar en documentos, y creo que tengo una idea clara de lo que hace , pero todavía estoy un poco sobre seguro el uso. La forma en que entiendo, se cambia entre diferentes secciones ELF (text para el código, data para los datos de escritura, bss para datos no inicializados, rodata para las constantes, y otros), y define nuevos cuando se desee. Creo que se podría cambiar entre ellas en función de si se define el código, los datos, los datos no inicializados, etc, pero ¿por qué crear una subsección para una función, como en el ejemplo anterior?


Cualquier ayuda con esto se aprecia. Si usted puede encontrar enlaces a tutoriales o documentos que explican en detalle mayor preferencia - comprensibles para un novato - Yo estaría muy agradecido.

Hasta ahora, el Utilizando como manual ha sido de alguna ayuda - tal vez puedas sacar más provecho de lo que yo, con más conocimiento.

¿Fue útil?

Solución

he estado programando brazo / pulgar durante muchos años una gran cantidad de ensamblador y necesitado muy pocas de las muchas directivas que hay.

.thumb_func es muy importante, ya fuera en punta por otro respondedor.

por ejemplo

.globl _start
_start:
    b   reset

reset:

.arm

.globl one
one:
    add r0,r0,#1
    bx lr

.thumb

.globl two
two:
    add r0,r0,#2
    bx lr

.thumb_func
.globl three
three:
    add r0,r0,#3
    bx lr


.word two
.word three

.arm o solía ser algo así como .code32 o .code 32 dice que este es el código brazo no código pulgar, que para su Cortex-M3 usted no necesita el uso.

.thumb asimismo, que solía ser .code 16 o tal vez que todavía funciona, el mismo acuerdo tiene el siguiente código no pulgar brazo.

Si las etiquetas que está utilizando no son etiquetas globales que es necesario rama a partir de otros archivos o indirectamente, a continuación, no necesitará el .thumb_func. Pero para que la dirección de una sucursal de una de estas etiquetas globales a calcular correctamente (bit menos significativo es un 1 para el pulgar y 0 para el brazo) que desea marcar como etiqueta pulgar o el brazo y el thumb_func hace que, de lo contrario tiene que establecer que poco antes de la adición de más de ramificación de código y la etiqueta no es exigible de C.

00000000 <_start>:
   0:   eaffffff    b   4 <one>

00000004 <one>:
   4:   e2800001    add r0, r0, #1
   8:   e12fff1e    bx  lr

0000000c <two>:
   c:   3002        adds    r0, #2
   e:   4770        bx  lr

00000010 <three>:
  10:   3003        adds    r0, #3
  12:   4770        bx  lr
  14:   0000000c    andeq   r0, r0, ip
  18:   00000011    andeq   r0, r0, r1, lsl r0

Hasta la .thumb el ensamblador es el código de brazo según se desee.

Tanto los dos y tres etiquetas / funciones son código pulgar como se desee pero los dos etiqueta tiene una dirección de número par y tres tiene la dirección de número impar adecuada.

Las últimas herramientas CodeSourcery se utilizaron para ensamblar, enlazar y volcar el ejemplo anterior.

Ahora, para el Cortex-M3 donde todo es pulgar (/ thumb2) thumb_func puede no ser tan importante, que sólo puede trabajar con la línea de comandos (muy fácil de hacer un experimento para averiguar). Es un buen hábito para tener aunque en el caso que nos alejamos de un pulgar único procesador de un núcleo normal de brazo / pulgar.

Los ensambladores general como para agregar todas estas directivas y otras formas de hacer las cosas se ven / sentir más como un lenguaje de alto nivel. Sólo estoy diciendo que no tiene que usarlos, cambié montadores para el brazo y el uso de muchos montadores diferentes para muchos procesadores diferentes y prefiero el enfoque menos es más, es decir, el foco en el conjunto del mismo y su uso como herramienta de algunos artículos específicos como sea posible. Normalmente no soy la excepción de la regla, sin embargo, lo que probablemente puede averiguar las directivas utilizado más a menudo por mirar lo que las directivas de la salida del compilador genera (y verificar la documentación).

unsigned int one ( unsigned int x )
{
    return(x+1);
}


    .arch armv5te
    .fpu softvfp
    .eabi_attribute 20, 1
    .eabi_attribute 21, 1
    .eabi_attribute 23, 3
    .eabi_attribute 24, 1
    .eabi_attribute 25, 1
    .eabi_attribute 26, 2
    .eabi_attribute 30, 2
    .eabi_attribute 18, 4
    .file   "bob.c"
    .text
    .align  2
    .global one
    .type   one, %function
one:
    .fnstart
.LFB0:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 0, uses_anonymous_args = 0
    @ link register save eliminated.
    add r0, r0, #1
    bx  lr
    .fnend
    .size   one, .-one
    .ident  "GCC: (Sourcery G++ Lite 2010.09-50) 4.5.1"
    .section    .note.GNU-stack,"",%progbits

hago uso de la .Align al mezclar los datos brazo y ensamblador pulgar o con ensamblador, se esperaría que el ensamblador para esa plataforma saber algo tan obvio como las instrucciones de mariposa están en los límites media palabra y las instrucciones brazo están alineados en límites de palabra . Las herramientas no son siempre tan inteligente. rociada sobre .aligns dolor suele

.text es el valor predeterminado de manera que es una redundancia poco, pero el dolor de costumbre. .text y .data son atributos estándar (no específico para armar) si está compilando para una combinación de ROM y RAM en su destino que puede cuidar (depende de lo que haces con la secuencia de comandos enlazador), de lo contrario .text funcionará para todo .

.size aparentemente el tamaño de la función de inicio de dicha Directiva. El ensamblador no puede resolver esto por sí solo, por lo que si el tamaño de esta función es importante para su código, escritura enlazador, depurador, cargador, lo que sea entonces esto tiene que ser derecha, si usted no tiene que molestarse. Una función es un concepto de todos modos duerma ensamblador de alto nivel realmente tiene funciones mucho menos la necesidad de declarar su tamaño. Y el compilador C sin duda la atención no funciona, sólo está buscando una etiqueta de rama en y en el caso de la familia del brazo es que el código pulgar o el código de brazo que se está ramificado a.

Usted puede encontrar la directiva .pool (hay un nuevo equivalente) útil si usted es perezoso con sus immediates (LDR rx, = 0x12345678) en largos tramos de código. Una vez más las herramientas no son siempre lo suficientemente inteligente como para colocar estos datos después de un salto incondicional, que a veces tienen contarles. Digo perezoso medio en serio, es doloroso que ver la etiqueta: .word cosa todo el tiempo y yo belivíspera, tanto las herramientas del brazo y gcc permitidos para ese acceso directo, por lo que lo uso tanto como cualquier otra persona.

nota también llvm da salida a una o dos .eabi_attribute adicional que es compatible con la versión del código de sourcery / mods a binutils, pero no está soportada (quizá aún) por las binutils lanzado GNU. Dos soluciones que el trabajo, la función de impresión de asm llvm Modificar no escribir los eabi_attributes o al menos escribir con un comentario (@) o lleve a la fuente binutils / mods de Sourcery código y construir binutils de esa manera. código sourcery tiende a GNU plomo (thumb2 apoyo por ejemplo) o tal vez backports nuevas características, así que supongo que estos attrubutes llvm estarán presentes en las binutils la línea principal antes de tiempo. He sufrido ningún efecto negativo por el recorte de los eabi_attributes fuera del código compilado llvm.

Aquí está la salida llvm para la misma función anterior, al parecer esta es la LLC que he modificado para comentar los eabi_attributes.

    .syntax unified
@   .eabi_attribute 20, 1
@   .eabi_attribute 21, 1
@   .eabi_attribute 23, 3
@   .eabi_attribute 24, 1
@   .eabi_attribute 25, 1
@   .eabi_attribute 44, 1
    .file   "bob.bc"
    .text
    .globl  one
    .align  2
    .type   one,%function
one:                                    @ @one
@ BB#0:                                 @ %entry
    add r0, r0, #1
    bx  lr
.Ltmp0:
    .size   one, .Ltmp0-one

El formato de archivo ELF está bien documentado y muy fácil de analizar si quieres ver realmente lo que las directivas específicas Elf (si los hay) están haciendo. Muchas de estas directivas son para ayudar al enlazador más que nada. .thumb_func, .text, .data por ejemplo.

Otros consejos

Las secciones de su programa están estrechamente relacionado con el formato ELF en el que la mayoría de los sistemas (Linux, BSD, ...) almacenan su objeto y archivos ejecutables. Este artículo debe darle una buena idea acerca ELF cómo funciona, lo que le ayudará a entender el porqué de las secciones.

En pocas palabras, las secciones dejó organizar su programa en diferentes áreas de memoria que tienen propiedades diferentes, incluyendo la dirección, el permiso para ejecutar y escribir, etc. Durante la etapa eslabón final, el enlazador utiliza un particular, guión enlazador que por lo general los grupos de todas las secciones del mismo nombre juntos (por ejemplo, todo el código de todas las unidades de compilación juntos, ...) y les asigna una dirección definitiva en la memoria.

En sistemas embebidos su uso es particularmente evidente: en primer lugar, el código de arranque (normalmente contenida en la sección .text) debe estar cargado en una dirección fija con el fin de ser ejecutado. A continuación, datos de sólo lectura se pueden agrupar en una sección de sólo lectura dedicado que se va a proyectar en el área de la ROM del dispositivo. Último ejemplo: la operación de sistemas de inicialización tienen funciones que se llaman únicamente una vez y luego nunca usaron después, desperdiciar espacio precioso recuerdo. Si todas estas funciones de inicialización se agrupan en una sección dedicación llamada, por ejemplo, .initcode, y si esta sección se establece en la última sección del programa, a continuación, el sistema operativo puede fácilmente recuperar esta memoria una vez inicialización se termina mediante la reducción de la parte superior límite de su propia memoria. Linux, por ejemplo, se conoce el uso de ese truco, y GCC le permite colocar una variable o método en una sección específica por postfixing con __attribute__ ((section ("MYSECTION")))

.type y .size son en realidad todavía bastante claro para mí también. Los veo como ayudantes para el enlazador y nunca los vi fuera del código generado ensamblador.

.thumb_func parece ser necesario sólo para la interfaz OABI de edad con el fin de permitir el interfuncionamiento con código de brazo. Si no está utilizando una vieja cadena de herramientas, es probable que no tenga que preocuparse por ello.

Me encontré con este cuando se trata de averiguar por qué ARM y el interfuncionamiento Pulgar rompieron con binutils recientes (verificado con 2.21.53 (MacPorts), también 2,22 (Yagarto 4.7.1)).

A partir de mi experiencia, .thumb_func funcionó bien con binutils anteriores para generar las chapas de interfuncionamiento correctas. Sin embargo, con los más recientes lanzamientos, la Se necesita directiva .type *name*, %function para asegurar la generación de chapa adecuada.

binutils lista de correo de entrada

soy demasiado perezoso para desenterrar una versión anterior de binutils para comprobar si la directiva .type es suficiente en lugar de .thumb_func para binutils anteriores. Creo que no hay ningún daño en la inclusión de ambas directivas en el código.

Editado: comentario actualizada sobre el uso de .thumb_func en el código, al parecer funciona para ARM-> Pulgar interfuncionamiento para marcar el pulgar rutina para generar chapas, pero pulgar> ARM interfuncionamiento falla a menos que la directiva .type se utiliza para marcar la función ARM .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top