Современное аппаратное обеспечение, как вы описываете, имеет программу, хранящуюся в ПЗУ, и универсальный микрокомпьютер (ЦП), выполняющий эту программу.
ЦП считывает информацию из ПЗУ, устанавливая адреса на своей адресной шине, а затем просит ПЗУ сообщить ему значение, хранящееся в этом месте. Возникает что-то вроде импульса чтения (в отдельной строке), который сообщает ПЗУ, чтобы сделать значение доступным в строках шины данных. Это, в двух словах, чтение.
Чтобы аппаратные средства что-то делали, ЦП в основном выполняет своего рода операцию записи. Он помещает значение, которое является просто кучей битов, если вы хотите посмотреть на него таким образом, на адресную шину, чтобы выбрать определенное устройство и, возможно, функционировать на этом устройстве, а затем выдает другую сигнальную линию, говорящую «напишите!» Устройство, которое распознает свой адрес на адресной шине, реагирует на этот сигнал, принимая данные с шины данных и затем выполняя любую функцию. Как правило, один из битов шины данных будет подключен в выходном устройстве к выходному каскаду мощности, то есть к транзистору, более мощному, чем те, которые используются только для вычислений, и этот транзистор подключит некоторое электрическое устройство к току, достаточному для его движения / свечения. /whatever.
Крошечные, дешевые устройства написаны на языке ассемблера, чтобы сэкономить на ПЗУ; в промышленных объемах даже небольшое количество памяти может повлиять на цену. Язык ассемблера специфичен для процессора; Некоторые чипы под названием «8051», «6502» и «Atmel (что-то или другое)» являются популярными. Более крупные устройства с более сложными требованиями могут иметь свою прошивку, написанную на C или C-подобном диалекте, что делает программирование немного легче, чем на ассемблере. Самые большие даже запускают код C ++. Скомпилировано, конечно.