C'est marrant ce que tu dis car c'est l'inverse de la tendance : il y a 20ans et plus, on programmait souvent en assembleur. Puis on ne l'a conservé que pour les sections critiques (vitesse d'exécution, code embarqué, etc). Enfin, on a tout passé en Java ou autre langage de haut-niveau. Bref, on s'est vachement éloigné du hardware et on a perdu en optimisation du code. Y'a bien un effort qui a été fait niveau graphique mais on doit encore utiliser des API spécifiques.
En total désaccord avec toi.
L'assembleur est clairement quand tu as besoin d'une opération que le langage ne propose pas et que le compilateur ne générera jamais :
choses qui sont beaucoup rapides avec de l'assembleur :
- lire le status word : retenue, overflow, underflow
- add avec retenue (pour faire des additions à plusieurs chiffres, chaque chiffre étant un mot)
- arithmétique en décimal (sur 68000)
- opération arithmétique avec exception en cas de débordement
- opération crypto (notamment AES)
choses qui ne sont possibles qu'en assembleur :
- test and set, compare and swap (atomique)
- opération arithmétique non interruptible (incrèmentation atomique...) sur Intel
- gestion des interruptions
- changement de mode
- gestion de la pagination, visibilité mémoire, accessibilité mémoire
bref pour une primitive. Ces primitives peuvent être présentées dans des macros ou fonctions en-lignes.
Au delà de ça, la programmation en assembleur parle le langage du processeur, mais n'est pas proche du métal : les instructions en assembleur sont complexes (surtout sur "CISC") et décomposées en opérations élèmentaires (fetch, op, store), le tout sur des registres physiques qui ne correspondent pas aux registres nommés en assembleur. Les opérations peuvent être exécutées en même temps (en l'absence de dépendance de données) et spéculativement (en présence de dépendance de contrôle); en cas d'anti-dépendance sur un registre, le processeur contourne le problème en utilisant plusieurs registre et parallélise les opérations. Il est très difficile pour un programmeur assembleur de gérer ce niveau d'abstraction, alors qu'un compilateur est fait pour ça.
La programmation assembleur a eu ses grandes heures sur des processeurs proches de leur langage assembleur, où la relation entre les instructions et leur exécution était relativement simple. Sur un processeur "moderne" disons à partir du Pentium c'est de moins en moins le cas.
La programmation assembleur n'incite pas du tout à optimiser les traitements, mais juste à micro-optimiser. Comme tout est très laborieux, on utilise souvent en assembleur des structures de données très simples (*), comme les listes chaînées, que des structures plus difficiles à implèmenter mais meilleurs quand il y a beaucoup de données (table de hachage, arbre rouges-noirs, arbres B...); comme une réorganisation du code avec modification d'une structure de donnée est une tâche très difficile sans le niveau d'abstraction nécessaire dans le code, cela a lieu rarement.
(*) Il est vrai que pour un petit nombre d'éléments, les structures les plus simples sont souvent plus efficaces en temps et en mémoire, car le raffinement a un coût (un B-tree est passablement complexe) et que les structures compliquées impliquent des algo compliqués avec plein de branchements qui bloquent la pipeline.
De plus, les choses qu'on faisaient "à la main" à une époques comme des calculs graphiques lourds (textures dans un jeu 3D par exemple) sont sous-traités à une carte graphique.
Les programmes sont gros et lourds principalement parce que les programmeurs sont indifférents à cela, qu'ils utilisent des "framework" monstrueux pour faire le moindre truc, et aussi
parce que beaucoup de programmeurs sont vraiment très médiocres.
Une fois que les opérations lourdes comme les calculs de textures dans un jeu sont sous traités, le reste est d'assez haut niveau, certains jeux sont programmés dans des langages interprétés (pour les réactions de l'IA).
Les programmes sont souvent limités par le nombre d'opérations disques ou de BDD qu'ils font : par exemple ce forum, pour fabriquer la moindre page HTML il faut plusieurs requête SQL; là tout va se jouer sur le fait d'avoir les bons index et de formuler les requêtes pour qu'ils soient utilisables. C'est tout l'art de bien décomposer et formaliser un problème.