Como alguien que ha escrito programas que se ejecutan sin un sistema operativo, ofrezco una respuesta definitiva.
¿Necesitaría un ejecutable un kernel de SO para ejecutarse?
Eso depende de cómo ese programa fue escrito y construido.
Podría escribir un programa (suponiendo que tenga los conocimientos) que no requiera un sistema operativo en absoluto.
Tal programa se describe como ser único .
Los cargadores de arranque y los programas de diagnóstico son usos típicos de los programas independientes.
Sin embargo, el programa típico escrito y integrado en algún entorno de sistema operativo host se ejecutaría en ese mismo entorno de sistema operativo.
Se requieren decisiones y acciones muy explícitas para escribir y construir un programa independiente.
... la salida del compilador es el código de máquina (ejecutable) que pensé que eran instrucciones directamente para la CPU.
Correcto.
Recientemente estuve leyendo sobre los kernels y descubrí que los programas no pueden acceder directamente al hardware, sino que tienen que pasar por el kernel.
Esa es una restricción impuesta por un modo de CPU que el sistema operativo utiliza para ejecutar programas, y se facilita mediante ciertas herramientas de compilación, como compiladores y bibliotecas.
No es una limitación intrínseca en cada programa escrito.
Entonces, cuando compilemos un código fuente simple, digamos con solo una función printf (), y la compilación produzca el código de máquina ejecutable, cada instrucción en este código de máquina se ejecutará directamente desde la memoria (una vez que el sistema operativo cargue el código en la memoria). ) ¿O será necesario que cada comando en el código de la máquina pase por el sistema operativo (kernel) para ser ejecutado?
Cada instrucción es ejecutada por la CPU.
Una instrucción que no es compatible o ilegal (por ejemplo, el proceso no tiene privilegios suficientes) causará una excepción inmediata, y la CPU ejecutará una rutina para manejar esta condición inusual.
UNA printf () La función no debe ser usada como un ejemplo de "código fuente simple" .
La traducción de un lenguaje de programación de alto nivel orientado a objetos a código de máquina puede no ser tan trivial como usted implica.
Y luego elige una de las funciones más complejas de una biblioteca de tiempo de ejecución que realiza conversiones de datos y I / O.
Tenga en cuenta que su pregunta estipula un entorno con un sistema operativo (y una biblioteca de tiempo de ejecución).
Una vez que el sistema se inicia y el sistema operativo recibe el control de la computadora, se imponen restricciones sobre lo que puede hacer un programa (por ejemplo, el sistema operativo debe realizar la E / S).
Si espera ejecutar un programa independiente (es decir, sin un sistema operativo), no debe iniciar la computadora para ejecutar el sistema operativo.
... ¿Qué sucede después de que el código de máquina se carga en la memoria?
Eso depende del medio ambiente.
Para un programa independiente, se puede ejecutar, es decir, el control se entrega saltando a la dirección de inicio del programa.
Para un programa cargado por el sistema operativo, el programa debe estar vinculado dinámicamente con bibliotecas compartidas de las que depende. El sistema operativo debe crear un espacio de ejecución para el proceso que ejecutará el programa.
¿Pasará por el núcleo o hablará directamente con el procesador?
El código de máquina es ejecutado por la CPU.
Ellos no "ir a través del núcleo" , pero tampoco ellos "hablar con el procesador" .
El código de la máquina (que consta de un código de operación y operandos) es una instrucción a la CPU que se decodifica y se realiza la operación.
Quizás el siguiente tema que debes investigar es Modos de CPU .