C’est tout à fait possible de faire une interface graphique directement en assembleur. La méthode la plus simple est évidemment de faire appel à une lib externe.
En supposant qu’on veuille utiliser cette lib (écrite en C++, mais la même chose peut être fait en C et probablement en Pascal aussi):
#include <iostream>
static int next_id = 0;
extern "C" {
int createWindow() {
int id = next_id;
next_id++;
std::cout << "ceateWindow " << id << "\n";
return id;
}
void closeWindow(int id) {
std::cout << "closeWindow " << id << "\n";
}
}
Essentiellement, on a deux fonctions: createWindow
qui ne prend aucun argument et retourne un int
, et closeWindow
qui prend un int
en argument et ne retourne rien. Pour compiler cette lib, on peut utiliser la commande clang++ -o my_lib.o my_lib.cc
.
Pour faire appel à cet lib en assembleur il suffit de déclarer les fonctions avec extern
et y faire appel en se référant aux conventions d’appel du système que tu utilises (x86–64 sur linux dans l’exemple):
section .data
global main
extern createWindow
extern closeWindow
section .text
main:
call createWindow
; window id is in rax, put it in rdi
mov rdi,rax
call closeWindow
; return 0
mov rax,0
ret
Le fichier peut se compiler avec nasm -f elf64 main.s -o main.o
.
Pour générer l’exécutable, il suffit de linker le tout avec clang++ -o main main.o my_lib.o
. À noter que clang va y ajouter la lib standard C++ (nécessaire pour la lib écrite en C++) qui contient le _start
qui s’occupera d’appeler le main
écrit en asm (en plus d’initialiser un certain nombre de trucs nécessaire pour la lib standard C++).
Suivant l’assembleur que tu utilises et le système pour lequel tu veux compiler ton programme, les choses peuvent être un peu différentes, mais le principe devrait rester le même.
Il est aussi possible de faire l’inverse: créer les fonctions nécessaire à la calculatrice en assembleur et ensuite faire appel à ces fonctions dans le langage que tu veux, ce qui te permet de gérer l’interface graphique dans ce langage. Voici un exemple rapide:
#include <iostream>
extern "C" {
int add(int, int);
}
int main() {
std::cout << "3 + 5 = " << add(3, 5) << "\n";
return 0;
}
section .data
global add
section .text
add:
mov rax, rdi
add rax, rsi
ret
Pour compiler et linker, on peut utiliser les même commandes que pour l’autre exemple.