visibles usuario unidad registros registro programa para instrucciones instruccion estados ejecucion control contador computadoras ciclo captacion arquitectura c assembly gdb cpu

usuario - ¿Cómo es posible leer los registros de la CPU usando un depurador que se ejecuta en la misma CPU?



registros visibles para el usuario (2)

Cuando estaba aprendiendo sobre ensamblaje, utilicé GDB de la siguiente manera:

gdb ./a.out (a is a compiled C script that only prints hello world) break main run info registers

¿Por qué puedo ver los registros utilizados por mi programa cuando estoy usando la misma CPU para imprimir los registros? ¿No debería el uso de GDB (o sistema operativo) sobrescribir los registros y solo mostrarme los registros sobrescritos? La única respuesta que puedo pensar es en el hecho de que mi CPU es de doble núcleo y que uno de los núcleos está siendo utilizado y el otro se guarda para el programa.


El sistema operativo mantiene el estado de los registros para cada subproceso de ejecución. Cuando examina registros en gdb, el depurador le está pidiendo al sistema operativo que lea el valor de registro desde el estado guardado. Su programa no se está ejecutando en ese momento, es el depurador el que lo es.

Supongamos que no hay otros procesos en su sistema. Aquí hay una vista simplificada de lo que sucede:

  1. El depurador se inicia y obtiene la CPU
  2. Debugger le pide al sistema operativo que cargue su programa
  3. El depurador le pide al sistema operativo que coloque el punto de interrupción
  4. Debugger le pide al sistema operativo que comience a ejecutar su programa. El sistema operativo guarda el estado del registro gdb y transfiere el control a su programa.
  5. Tu programa llega al punto de interrupción. El sistema operativo toma el control, guarda el estado de registro de su programa, vuelve a cargar los registros de gdb y devuelve la CPU a gdb.
  6. El depurador le pide al sistema operativo que lea los registros del programa desde el estado guardado.

Tenga en cuenta que este mecanismo es parte de los deberes normales de un sistema operativo multitarea, no es específico para la depuración. Cuando el programador del sistema operativo decide que se debe ejecutar un programa diferente, guarda el estado actual y carga otro. Esto se denomina cambio de contexto y puede suceder muchas veces por segundo, lo que da la ilusión de que los programas se ejecutan simultáneamente, incluso si solo tiene un único núcleo de CPU.


En los viejos tiempos de los sistemas operativos de tarea única, las únicas cosas que podían interferir en la ejecución de su programa eran interrupciones. Ahora, los manejadores de interrupción tienen el mismo problema del que usted está hablando, su programa está calculando algo, el usuario presiona una tecla - interrupción - la rutina del servicio de interrupción tiene que hacer un trabajo pero no debe modificar un solo registro en el proceso. Esa es la razón principal, la pila se inventó en primer lugar. Una rutina de servicio de interrupción de DOS 80x86 habitual se vería así:

push ax push cx push dx push bx push si push di push bp // no need to push sp [do actual work, caller registers avaiable on stack if needed] pop bp pop di pop si pop bx pop dx pop cx pop ax iret

Esto era incluso tan común, que se creó un nuevo par de instrucciones pusha y popa (para push / pop all) para facilitar esta tarea.

En las CPU actuales con aislamiento de espacio de direcciones entre los sistemas operativos y las aplicaciones, las CPU proporcionan algún sistema de estados de tareas y permiten que el sistema opere las tareas (las interrupciones pueden funcionar de manera similar a lo descrito anteriormente, pero también pueden manejarse mediante conmutación de tareas). Todos los sistemas operativos modernos utilizan este tipo de sistemas de estados de tareas, donde la CPU guarda todos los registros de un proceso mientras no se ejecuta activamente. Como Jester ya explicó, gdb solo le pide al sistema operativo que depure estos valores en el proceso y luego los imprime.