Mi programa de microcontrolador no se puede restablecer. ¿Ese hermano o hermana mayor sabe cómo agregarlo? Está en lenguaje C, gracias.
Recomendar una publicación para usted
main()
{
código de carácter sin firmar rst[]={0xe4,0xc0,0xe0 ,0xc0,0xe0,0x32}; // Restablecer código
(*((void (*)())(rst)))( // Ejecuta la línea de código anterior y usa la primera. array como llamada de función
}
Originalmente le dije que incrustara el siguiente código:
clr a
push acc p>
push acc
reti
Como resultado, reprodujo el párrafo anterior y el contenido de la matriz primero [] era exactamente el código de máquina ensamblador anterior. lo que hizo fue
Los datos de la primera matriz se guardan como código, y luego la dirección absoluta se usa para apuntar a la matriz, y el código en la matriz se ejecuta como
función. ¡De hecho pasó!
Creo que hay un problema. Aun así, la llamada de dirección absoluta debería escribirse como (*((void (*)())(&rst)))()
Sí, respondió que en ese caso, la dirección del primero se pasaría como parámetro a la función de dirección absoluta, y la dirección real llamada por LJMP no era la dirección del primero, sino una dirección incierta. Así que lo intenté según lo que dije
Mirando los resultados del ensamblaje, realmente pasé la dirección del primero a R1 R2, y finalmente llegó la función absoluta LJMP
Una dirección inexplicable fue subido, ¡maldita sea!
Parece que C es realmente un caballo salvaje que no es fácil de controlar. Este estudiante junior tiene una mejor comprensión que yo. Tengo 30 años y he estado haciendo esto durante muchos años.
p>Todavía no estoy a su nivel. ¡Ay, solo he estudiado durante unos días y después de leer el libro durante unos días, estoy tan bueno en eso que estoy convencido!
l Primero analice el código en lenguaje C de la publicación
La primera oración define una matriz primero []. Los datos en la matriz son el código de máquina ensamblador que completa la función de reinicio. La correspondencia específica
Es: clr a == 0xe4, push acc == 0xc0,0xe0, reti ==0x32
La segunda oración es el uso de un puntero de función. El uso del puntero de función es un poco complicado, consulte Escribí un libro :) y la siguiente es una introducción rápida.
La forma de definición de un puntero de función cuyo valor de retorno es una función nula es la siguiente:
void (*p) ( )
Cuando el puntero de función se le asigna un valor, puede Para llamar a una función a través de un puntero de función, la forma de llamada es la siguiente,
(*p) ( );
o la forma simplificada equivalente:
p ( );
Suponiendo que primero es un puntero de función, el siguiente formulario de llamada puede restablecer el microcontrolador.
(*rst ) ( );
Pero desafortunadamente, primero no es un puntero de función, sino un nombre de matriz. Aunque ambas son direcciones, el nombre de la matriz no se puede llamar directamente.
Al igual que asignar la variable de tipo char a a la variable de tipo int b, (int) representa la conversión de tipo forzada:
b = (int) a
Puntero de función La fórmula de conversión de tipo forzada es la siguiente (la filosofía del lenguaje C es definir el formulario y usarlo de manera consistente):
( (void (*)()) rst
En De esta manera, el primero convertido se puede utilizar como puntero de función. La forma de llamada simple es la siguiente:
#define K ( (void (*)() ) rst
(*K) ( )
O:
( * ( void (*)( ) )rst ) ( );
Esta declaración completa el reinicio y función de reinicio.
La prioridad del operador de conversión de tipo () es la misma que la prioridad del operador de puntero *.
La dirección de combinación de los dos es de derecha a izquierda, por lo que la declaración anterior puede completar la función de reinicio. Para estar seguros, a algunos programadores les gusta añadir paréntesis:
#define K ( ( (void (*)() ) rst )
( *K) ( )
o
( *( ( void (*)( ) )primero ) ) ( );
Dado que no hay parámetros de entrada, lo anterior Una forma más rigurosa de escribir el código de reinicio es:
#define K ( ( (void (*)(void ) ) rst )
(*K) ( )
O
( *( ( void (*)(void ) )rst ) ) ( );
l Explicación sobre el autor del post
Nunca cometa un error en la forma "&rst". Para una matriz unidimensional, el nombre de la matriz primero representa la dirección. Las dos formas siguientes son equivalentes. ecuación:
rst == &rst[0]
No es necesario pasar el puntero de función completo como parámetro. Simplemente llama a rst como la dirección de ejecución del programa. también es problemático
Debe mencionarse una cosa más. El hecho de que pueda pasar la compilación o incluso generar código correcto no significa que una determinada declaración deba ser correcta.
Para declaraciones muy complejas, se debe considerar la compilación. La posibilidad de que el procesador no sea estricto o incluso falle.
La estructura de Harvard y un gusano.
Tenga en cuenta la palabra clave. El código se utiliza al definir la matriz primero [], que es exclusivo de C51. La palabra clave significa definir la matriz en
espacio de programa
estructura de Harvard y estructura de Princeton:
.Estructura Harvard. ——El espacio del programa y el espacio de almacenamiento están separados. C51 es una estructura Harvard menos estricta; aunque las líneas de dirección están separadas, el DSP es una estructura Harvard mejorada.
La CPU Pentium en la PC es una. Estructura de Princeton: el espacio de datos y el espacio del programa se abordan de manera uniforme.
Si el código de máquina ensamblador de los primeros datos de la matriz es el código de máquina para eliminar el archivo, ¿cuenta esto con virus? p>
Un virus gusano alguna vez fue popular. Su mecanismo de ataque consiste en guardar código malicioso en un archivo de texto y luego ejecutar el texto a través de
llamadas de puntero. Muchos programas antivirus también incluyen archivos de texto. no será consultado.
Tanto los programas como los datos están en formato binario. Si el espacio de datos y el espacio del programa están codificados de manera uniforme, los datos, por supuesto,
se pueden ejecutar como un programa.
En este punto, relativamente hablando, la seguridad de la CPU de la estructura de Harvard será un poco mejor. Sin embargo, las aplicaciones integradas rara vez tienen virus, por lo que generalmente no es necesario preocuparse por ellos.
l Una mejor manera de restablecer el microcontrolador
La explicación en lenguaje ensamblador en la publicación es la siguiente:
clr a //Clear ACC=0 p>
push acc //Empuja 0 a la pila - 8 bits
push acc //Empuja 0 a la pila nuevamente - 8 bits nuevamente
reti //Volver a dirección 0 para ejecutar.
El método de reinicio propuesto por el autor de la publicación es más problemático. Un método de reinicio más simple es (extraído de "Defectos y trampas de C"):
( * ( void (*). )( ) ) 0 ) ( );
El método de análisis de esta oración es el mismo que el anterior, pero es más refinado y no hay declaraciones de ensamblaje redundantes.
El método de reinicio anterior se puede llamar reinicio de software.
Existe una gran diferencia entre el reinicio del software y el reinicio de encendido real: la mayoría de los registros tienen ciertos valores de reinicio durante el reinicio del software
el reinicio solo equivale al inicio; desde la dirección 0 Sólo para la ejecución, el registro no cambiará a un valor de reinicio definido.
Si el usuario desea programar un reinicio de encendido, simplemente no active el dispositivo de vigilancia en el programa. La mayoría de los microcontroladores tienen perros guardianes.