¿Cómo invoco una función C en otro módulo desde el ensamblador en línea en IAR EWARM?

2

No sé si se recomienda o no, pero estoy seguro de que alguien me dará una advertencia severa si no lo hace. He publicado un duplicar en stackoverflow, sin embargo, esto puede ser apropiado aquí ya que es para una plataforma integrada y una serie de desarrolladores integrados frecuentan este intercambio de pila. Tampoco hay mucha tracción por allí ...

Tengo un poco de ensamblaje en un manejador de fallas. El conjunto está destinado básicamente a pasar el puntero de pila actual como un parámetro (en R0). Parece que ...

__asm("    mov     r0, sp\n"
  "    bl      SavePC\n"
  "    bx      lr");

Esto funciona bien cuando SavePC está en el mismo archivo c. Sin embargo, cuando SavePC se coloca en otro archivo c no tengo suerte. He intentado IMPORTAR la función como tal ...

__asm("IMPORT SavePC\n"
" mov r0, sp\n"
" bl SavePC\n"
" bx lr");

... pero debo estar haciendo algo incorrecto. El compilador reporta lo siguiente ...

Error[Og005]: Unknown symbol in inline assembly: "IMPORT" 
Error[Og005]: Unknown symbol in inline assembly: "SavePC" 
Error[Og006]: Syntax error in inline assembly: "Error[54]: Expression can not be forward"
Error[Og005]: Unknown symbol in inline assembly: "SavePC" 
Error while running C/C++ Compiler 

El archivo c con el ensamblaje incluye el archivo de encabezado con el prototipo SavePC ...

extern void SavePC(unsigned long);

Sugerencias?

    
pregunta Jason

2 respuestas

2

Usar extern es un mal hábito ya que es propenso a errores. El estándar C-99 proporciona una alternativa segura para extern. Debe escribir la función prototipo en el archivo de encabezado sin una palabra clave externa. Luego incluya el archivo de encabezado en ambos archivos C. El enlazador es responsable de vincular la función en diferentes archivos.

Ejemplo:

Archivo: custom_header.h

void SavePC(unsigned long);

Archivo: source_c_file.c

#include "custom_header.h"

void SavePC(unsigned long)
{
      ....
      ....

      ....

}

Archivo: user_c_file.c

#include "custom_header.h"

void someFunction(void)
{
.
.
.

__asm("    mov     r0, sp\n"
  "    bl      SavePC\n"
  "    bx      lr");

.
.
.
}
    
respondido por el Kanwar Saad
1

Algunas cosas que podrías ver

A menudo, el lenguaje ensamblador debe usar un nombre decorado con un guión bajo ("_SavePC") para referirse a una función C que se define en C sin un guión bajo ("SavePC"). (El nombre en lenguaje ensamblador de las funciones de C ++ tiene mucha más decoración).

Solo uso la palabra clave "extern" en variables globales, no en funciones globales, exactamente como describe Kanwar Saad.

¿Ha considerado tal vez escribir ese bit de código en C, en lugar de en lenguaje ensamblador, y dejar que el compilador maneje los detalles de la convención de llamadas? Los compiladores de C de hoy a menudo admiten una sintaxis especial que le permite escribir dichos controladores en C más o menos pura, a menudo con algo así como un especificador "__interrupt", pero los detalles exactos varían de un compilador a otro. (Es posible que, al igual que muchos compiladores de C más antiguos, el compilador que está usando ahora requiera escribir cosas como controladores de fallas y tablas de vectores de interrupción en lenguaje ensamblador, ¿ha considerado tal vez la actualización a una cadena de herramientas de C más moderna como GNUARM o YAGARTO que utiliza gcc?)

La secuencia

bl      SavePC
bx      lr

probablemente crea un bucle infinito. ¿Has considerado usar algo más como los controladores de fallas difíciles ya escritos y probados por otras personas? Tal vez intente con a b c d o e ? Si tienes suerte, al menos uno trabajará para ti.

Si ninguno de esos pequeños detalles ayuda, puedes considerar usar el siguiente proceso general:

Proceso general

Cuando quiero llamar a una función C desde algún lenguaje ensamblador, yo

  • escriba un fragmento de código de prueba temporal "similar" en C: un código auxiliar que envía los mismos tipos de parámetros a la función y obtiene los mismos tipos de valores de retorno, pero tal vez falte alguna funcionalidad crítica.
  • compílelo con la opción especial que produce un archivo de texto lleno de mnemónicos en lenguaje ensamblador
  • copiar y pegar ese esqueleto en lenguaje ensamblador en mi lenguaje ensamblador
  • Pruebe el sistema: ensamble, compile, vincule, etc. el código de prueba no modificado para asegurarse de que realmente compila, vincula y funciona de la manera que espero.
  • Confíe el archivo de lenguaje ensamblador que se vincula correctamente al sistema de control de versiones (aunque todavía falte alguna funcionalidad crítica)
  • Complete la funcionalidad crítica que falta.
  • Probar el sistema. Invariablemente, descubro que algo se ha roto tanto que ni siquiera termina de vincularse.
  • Vuelva a la versión de enlace correcto del código de ensamblaje
  • Intente completar la funcionalidad crítica que falta.
  • Repita hasta que sea lo suficientemente bueno para enviar.

sugerencias para programación mixta de C y ensamblajes

borrador de un libro sobre la programación en lenguaje ensamblador ARM

    
respondido por el davidcary

Lea otras preguntas en las etiquetas