Niemand schreibt heute mehr direkt Assembler!!
Wichtiger ist jedoch, dass gerade für Hochleistungssysteme ein tiefergreifendes Verständnis von Prozessorarchitekturen herrscht, und man dann in Quelltexte von C (seltener C++) kurze Abschnitte so auslegt, dass sie hochoptimal durchlaufen werden. In den meisten Fällen kann man hier mit speziellen Compiler-Hints arbeiten (inline, const), speziellere Funktionen verwenden, die optimaler ablaufen (alloca, math), oder sich auch mal nicht zu schade zu sein, einen Haufen "goto"s ineinander zu verschachteln - wie gesagt, wir reden hier von kritischen und eng begrenzten Stellen.
Gleichwohl gibt es immer wieder Fällen, in denen die hochsprachlichen Möglichkeiten von C einfach noch zu beengt sind. So ist besonders schnelles Multithreading bestens mittels der speziellen CPU Instruktion "test-and-set" zu realisieren, neuere CPUs besitzen die Möglichkeit, eine kurz laufenden Thread abzuspalten, wofür das verallgemeinerte Managment des Betriebssystems einfach zu heftig ist - und man kann durch optimierte Zuweisung von Registern manch verquere Compileroptimierung auf den richtigen Pfad führen.
Natürlich hab ich auch reine Assemblerprogramme schon geschrieben - allerdings sollte man dort darauf wert legen, einen ordentlichen Makroassembler einzusetzen. Auch bei der Einbettung in C sollte man viel Gebrauch machen von dessen Makro-Präprozessor und der Expansion von Code durch Inline-Prozeduren. Letztlich denke ich, dass es nur sehr wenige Fälle gibt, in denen man auf die hochsprachliche Hilfe von C verzichtet - eigentlich nur bei Boot-ROMs, wo der Einsprungpunkt eben nicht "main" ist, sondern eine spezielle Adresse, und das C Speichermanagement noch nicht da ist, sonder womöglich die Segementtabellen direkt angefasst werden.
In anderen Fällen zeigt sich, dass Assembler vor allem als Synthese vorkommt - in dem man zur Laufzeit ein kleines Programm compiliert, und dieses an einen Koprozessor übergibt. Dies war früher ein Matheprozessor, derzeit verbreitet ist auf den PCs vor allem der Grafikprozessor, aktuell wird ein Kryptographie-Chip mit Spezialroutinen geladen, und in der Zukunft könnten verallgemeinerte Cell-Blöcke weitere Verbreitung finden.
Den PFE Forth Interpreter habe ich stark für verschiedene Rechnerarchitekturen optimiert - er nennt sich "Portable Forth Environment", da er auch ohne solche Optimierung auskommt, aber man kann die Ausführungsgeschwindigkeit stark beschleunigen. Darin inbegriffen ist die Art, aus dem Forth Quellcode beim Laden umgehend Maschinencode zu generieren - ähnlich wie es in jüngerer Zeit auch Java/.NET Umgebungen mit ihrer JIT-Funktionalität machen, der "Just'In'Time" Compilierung, die beim Start eines Programms auftritt.
Das SDL_stretch ist eine Mini-Bibliothek, die Blit-Operationen für moderne x86-PCs maximiert. Die SDL Grafikbibliothek enthält dabei schon ein Copy-and-Mask-Blit für Bereiche, jedoch kein Scale-and-Mask-Blit. Den brauchte ich für einige SDL-basierte Emulatoren wie dem Universal Amiga Emulator.
Weitere prozessorspezifische Anteile finden sich auch in alten Treibern für den Linux-Kernel. Manche Hardware hat man am besten direkt angesprochen. In neuerer Zeit bietet der Linux-Kernel allerdings für nahezu alle Zugriffe schon ausgereifte Makros (mit Assembler-Stücken), die auch deshalb verwendet sein sollten, da dann auch eine Virtualisierung der Treiber vereinfacht wird.