Jeder Prozessortyp hat einen bestimmten Befehlssatz, grundsätzlich können diese Befehlssätze recht unterschiedlich ausfallen. Grundsätzlich unterscheidet man da zwischen RISC (Reduced Instruction Set Computer) und CISC (Complex Instruction Set Computer) Prozessoren. Die einen haben einen kleinen Befehlssatz, aus dem man komplexere Befehlsketten erst zusammenbauen muss, die CISC Prozessoren haben hingegen einen größeren Befehlssatz mit teils komplexen Befehlen, die direkt in Hardware implementiert sind, beispielweise sowas wie sinus(x).
Assembler ist quasi eine äquivalente Sprache zu Maschinencode und unterscheidet sich dadurch auch wieder zwischen den Prozessortypen. Maschinencode selbst ist letztendlich natürlich binär und dadurch scheiße zu programmieren, genau deshalb hat man eine besser lesbare, äquivalente Sprache in Form von Assembler erschaffen. Immer noch zu umständlich -> Hochsprachen, die weitere Abstraktionsebenen von der Hardware bereitstellen.
Und daraus folgt, dass ich beim kompilieren von einem C Programm für x86 und für ARM unterschiedliche Ergebnisse rausbekomme, da der Compiler meine abstrakte Programmiersprache eben in die jeweils vorhandenen Befehlssätze kompiliert.
Der Prozessor holt sich dann über den Datenbus in Verbindung mit dem Adressbus seine Daten, wobei ein Befehl an den Prozessor dabei wiederum ein Datum darstellt. Der Prozessor holt sich also ein Datum von Adresse xy und das könnte ein Befehl sein oder auch nur ein einfacher Zahlenwert. Ich hoffe es ist verständlich, was damit gemeint ist. Das nennt man Von-Neumann-Architektur, es gibt keine unterschiedlichen Speicher für Daten und Programmcode.
Und damit kommen wir zur eigentlichen Frage vom TE: wenn ich den in Hardware implementierten Befehlssatz vom Prozessor kenne, dann kann ich natürlich auch Programme realisieren. Darauf aufbauend werden Betriebssysteme realisiert, die zwischen Hardware und restlicher Software abstrahieren. Auch heutzutage sind Betriebssystemkernel größtenteils in Assembler und der nächsten Abstraktionsebene "C" realisiert.
Kurz gesagt: wenn ich weiß, was wie sich der Prozessor verhält, wenn er eine bestimmte Folge von Binärcode (0/1) geschickt bekommt, kann ich anfangen Software zu realisieren. Wenn man ganz tief in die Hardware schaut, dann sind die Nullen und Einsen kleine Spannungsunterschiede, die als Null oder Eins interpretiert werden.
Es waren einige lustige Antworten dabei. Mit dem BIOS hat das nichts zu tun und in Hexadezimal schreiben, naja das ist einfach nur ein anderes Zahlensystem. Wenn ich einfach nur die Zahlenfolge "10" habe, dann wäre das als Dezimalzahl interpretiert die 10, als Dualzahl entsprechend die 2 und als Hexadezimalzahl die 16. Maschinencode ist stehts binär.
Ich hoffe ich hab mich halbwegs verständlich ausdrücken können und nicht irgendwas verrafft, denn es ist schon spät.