Прошло уже два года а то и больше. Ответ на вопрос я, конечно, теперь уже знаю. Для таких же пытливых, каким был я, распишу всё в деталях.
На самом низком уровне (из тех, что имеет смысл рассматривать в данном вопросе) лежит ОС, на долю которой выпадает управление буквально всем и, в частности, стандартным вводом/выводом.
Начиная с этого момента, за винду в рамках данного ответа не ручаюсь и говорить буду только про POSIX.
По сути та консоль с текстом, которую видит пользователь, это обычная программа (в некоторых случаях модуль ядра), которая называется эмулятором терминала. Задача эмулятора - запустить другую программу как дочерний процесс, перенаправлять все нажатые клавиши ей в stdin и выводить на экран то, что она пишет в stdout и stderr (обычно с поддержкой управляющих последовательностей ANSI и прочей мишуры).
Любая программа не может работать с файлами, коносолью и вообще с чем-либо, минуя ОС. stdout является обычным файлом, в который можно писать ровно так же, как и в любой другой. Запись в файл, обычно, происходит в несколько этапов: сначала открываем его, тем самым получая дескриптов, потом вызываем сисколл (например write), который запишет текст в этот дескриптор.
Отвечая на первый вопрос: stdout открывать не надо и искать его тоже не надо: это "виртуальный" файл, который автоматически открывается для каждой программы с дескриптором 1.
Отвечая на второй вопрос: данные в stdout записываются ровно так же, как и в любой файл.
Эта информация универсальна, потому что так или иначе любой вывод текста в консоль сводится к этому механизму.
Переходя к виртуальным машинам, нужно сразу вспомнить, что они сами тоже написаны на каком-то языке. Вообще говоря, для вывода текста в консоль виртуальная машина может просто использовать средства языка, на котором она реализованна, но этот вариант не так интересен.
Сами по себе виртуальные машины обычно реализованы как интерпретатор/JIT-компилятор (а иногда даже AOT-компилятор!) байт-кода. Обычно под вывод не выделяют отдельную инструкцию. В виртуальных машинах часто присутствует механизм, позволяющий взаимодействовать с нативным кодом (то есть кодом на низкоуровневых языках, собранным в бинарник), так называемый native function interface. Этот механизм, конечно, работает во многом усилиями языка, на котором реализована ВМ, и именно он позволяет взять и вызвать функцию, которая под капотом уже вызывает соответствующий сисколл.
Объяснение, конечно, относительно детальное, но всё ещё сильное упрощённое. Надеюсь, интересующимся я помог.