В 99,9% случаев — на языках высокого уровня. Как слой более низкого уровня используются три вещи.
1. Стандартная библиотека языка.
2. Внутреннее API ОС (WinAPI/POSIX/DOS).
3. Чужие низкоуровневые библиотеки.
Есть такое понятие «полнота по Тьюрингу» — грубо говоря, это значит, что язык способен решать те же задачи, что и машина Тьюринга (простое гипотетическое программируемое устройство). Все языки программирования полны по Тьюрингу, то есть ими можно закодировать любой алгоритм, зачем ассемблер?
Ассемблер используется ограниченно во внутренних циклах, где важна скорость.
Здесь под «низким уровнем» понимается «мало автоматизации», «очень тонкая прослойка между API операционной системы и нашим новым интерфейсом», «минимум управления памятью» — то есть функция, например, принимает не std::string, а указатель на нуль-терминированную строку const char*. И для написания библиотек любят языки, способные работать на низком уровне — в первую очередь Си, Си++ и Паскаль. Если нет ограничения по скорости, ассемблер не обязателен.