¿Cómo puedo encontrar la posición actual de la pila sin un puntero de pila en la programación del microcontrolador?

0

En una entrevista, me preguntaron cómo encontraría la posición de la pila sin utilizar el puntero de pila que le dieron con el límite superior de pila y la profundidad de pila. Me pidieron que ilustrara el uso de C o lenguaje ensamblador incrustado para 8051. No pude dar la respuesta. Más tarde busqué en Google lo mismo, pero no pude conseguir uno. ¿Alguien puede ayudarme, por favor, a encontrar la respuesta?

    

3 respuestas

6

Como se señaló en los comentarios, no usar el puntero de pila cuando hay uno es realmente tonto y nadie lo haría en la vida real. Al igual que escribir un programa FizzBuzz.

Sí, necesita conocer las arquitecturas de los procesadores, pero eso no es lo principal que los entrevistadores quieren saber. Podrían descubrirlo simplemente haciéndole preguntas de conocimiento.

De lo que realmente se trata realmente es su enfoque para la resolución de problemas: ¿Dice simplemente que no sabe? ¿Te sientas allí en silencio, aparentemente sin hacer nada, antes de anunciar que no lo sabes? ¿Empiezas a llorar? ¿Tratas de hablar (con los entrevistadores o contigo mismo) sobre el problema para discutir y / o descartar las diferentes maneras de abordar el problema? ¿Empieza a dibujar sus opciones en papel o dibuja un mapa mental? Estas son las cosas que los entrevistadores verán, y algunas de ellas causan una mejor impresión que otras.

Así que aquí está la parte no interesante de la respuesta, el algoritmo:

  1. Inserte un valor conocido en la pila, por ejemplo, 0x77 .
  2. Escanee todo el espacio de pila para este valor (ya sabe inicio y tamaño máximo de la pila).
  3. Una vez que encuentre 0x77 en algún lugar, ejecute una instrucción POP y presione 0x88 .
  4. Verifique esa dirección de memoria nuevamente. Si cambió a 0x88 , esa es la parte superior de tu pila. Ve al 6.
  5. Si no cambió, continúe escaneando y repita los pasos 3-5 hasta que llegue al final de la pila o encuentre un valor cambiante.
  6. Ejecuta un POP para limpiar después de ti.

Nota: Si no conoce la ubicación y el tamaño de la pila, también puede escanear todo el espacio de direcciones, lo que probablemente no sea tan grande en un microcontrolador. Solo debes tener cuidado de que tu implementación no use RAM, para que no coloque el valor buscado en algún lugar fuera de la pila y se confunda.

    
respondido por el Fritz
0

Esta es en realidad una pregunta de programación pura, pero por desgracia ...

Puedes encontrar la ubicación de la pila colocando una variable en la pila, luego toma la dirección de la variable:

function stack_check()
{
   int i;

   int *p = &i;
   printf("End of stack is %p\n", p);
}

Nicked from arduino.stackexchange.com

    
respondido por el JvO
-1

[Editar] Esta no es la respuesta correcta, ya que la respuesta de Fritz es claramente lo que se buscaba :) Pero dejaré que esta respuesta permanezca aquí para la discusión de las convenciones de llamadas. Especialmente las funciones variadic (aquellas con un número variable de argumentos) son interesantes a este respecto.

Esto se suma a la respuesta de JvO, que sugiere obtener el puntero de pila obteniendo la dirección de una variable asignada de pila. También he usado esta técnica. Pero Olin observó que la variable podría no asignarse desde la pila, lo que también es cierto. Esto me llevó a pensar en el siguiente enfoque:

void *GetStack(int *i, ...) {
    return &i;
}

La variable que pasa los argumentos garantiza que el primer parámetro debe colocarse en una dirección RAM, ya que el resto de los argumentos tienen la garantía de seguirlo en la memoria (el primer argumento debe ser pasable a una macro va_start), y como tal hay una buena probabilidad de que esté en la pila. Entonces, si bien no identifica la dirección exacta de la parte superior de la pila, podría estar bastante cerca y debería valer la pena intentarlo si el método de JvO no funciona.

PS. Si sabe que el primer argumento debe o no debe ser un puntero, continúe y edite la respuesta.

[Editar] Acabo de darme cuenta de que la pregunta era específica para 8051, así que hice una prueba rápida en el compilador SDCC. SDCC utiliza una asignación de árbol de llamadas para superponer las variables locales en direcciones estáticas de forma predeterminada y el código

void * GetStack() {
  int i; 
  return &i;
} 

compila en

_GetStack: 
  mov dptr,#_GetStack_i_1_1
  mov b,#0x00
  ret

Esto significa que i no está en la pila, es una dirección estática decidida por el compilador. Creo que es tan dependiente del compilador y del modelo de memoria que asm es la única manera real de hacerlo.

Mi primera función sugerida

void *GetStack2(int *i, ...) {
    return &i;
}

parece mejorar un poco, se compila en:

GetStack2:
        push    _bp
        mov     _bp,sp
        mov     a,_bp
        add     a,#0xfb
        mov     r2,a
        mov     r3,#0x00
        mov     r4,#0x0
        mov     dpl,r2
        mov     dph,r3
        mov     b,r4
        mov     sp,_bp
        pop     _bp
        ret

que al menos hace referencia a SP. Con asm, el código podría ser mucho más limpio, supongo.

    
respondido por el PkP

Lea otras preguntas en las etiquetas