Differenze tra le versioni di "Inserire nella libreria condivisa esterna .so anche codice Assembly"
(32 versioni intermedie di uno stesso utente non sono mostrate) | |||
Riga 1: | Riga 1: | ||
− | E' possibile inserire in una libreria esterna condivisa .so, [[Creare_una_Libreria_condivisa_(Shared_Library)_.so|da noi realizzata]], anche codice ''Assembly'', al fine di ottenere prestazioni ancor più veloci. | + | E' possibile inserire in una libreria esterna dinamica condivisa (.so), <SPAN Style="text-decoration:underline">[[Creare_una_Libreria_condivisa_(Shared_Library)_.so|da noi realizzata]]</span>, anche codice ''Assembly'', al fine di ottenere prestazioni ancor più veloci. |
+ | |||
+ | In particolare sono possibili due modalità: | ||
+ | * con la funzione ''asm()''; | ||
+ | * con la funzione ''__asm__()'' . | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==Riepilogo schematico dei tipi di registri di memoria in base alla quantità di memoria resa da ciascuno disponibile== | ||
+ | Di seguito mostriamo un breve e schematico ripilogo dei tipi di ''[https://en.wikipedia.org/wiki/X86#x86_registers registri di memoria]'' (registri del processore) utilizzabili nel linguaggio ''Assembly'' su un sistema a 64-bit in base alla quantità di memoria resa da ciascuno di essi disponibile: | ||
+ | ================ '''rax''' (64 bit) | ||
+ | ======== '''eax''' (32 bit) | ||
+ | ==== '''ax''' (16 bit) | ||
+ | == '''ah''' (8 bit) | ||
+ | == '''al''' (8 bit) | ||
+ | |||
+ | o visto anche così: | ||
+ | |__'''64'''__|__56__|__48__|__40__|__'''32'''__|__24__|__'''16'''__|__'''8'''___| | ||
+ | |__________________________RAX__________________________| | ||
+ | | |____________EAX____________| | ||
+ | | |_____AX______| | ||
+ | | |__AH__|__AL__| | ||
+ | |||
− | |||
==Uso della funzione ''asm()''== | ==Uso della funzione ''asm()''== | ||
− | + | Una prima modalità mostra come è possibile integrare il codice ''Assembly'' all'interno del linguaggio C in un sistema a 32-bit mediante la funzione ''asm()'': | |
static unsigned int car <FONT color=#B22222>asm("raxregistro")</font>; | static unsigned int car <FONT color=#B22222>asm("raxregistro")</font>; | ||
Riga 17: | Riga 39: | ||
===Problemi di compilazione nei sistemi a 64-bit durante la creazione di una Libreria .so=== | ===Problemi di compilazione nei sistemi a 64-bit durante la creazione di una Libreria .so=== | ||
− | |||
Si è riscontrato nei sistemi a 64-bit che durante la compilazione, qualora nel codice vi siano una o più variabili, viene restituito il seguente avviso di errore: | Si è riscontrato nei sistemi a 64-bit che durante la compilazione, qualora nel codice vi siano una o più variabili, viene restituito il seguente avviso di errore: | ||
Riga 67: | Riga 88: | ||
===Esempio pratico di creazione ed uso di una libreria dinamica condivisa, contenente codice ''Assembly'', con Gambas=== | ===Esempio pratico di creazione ed uso di una libreria dinamica condivisa, contenente codice ''Assembly'', con Gambas=== | ||
Mostriamo di seguito un semplice esempio (in sistema a 64-bit), nel quale sarà creata una libreria dinamica condivisa esterna, contenente codice ''Assembly'', e sarà quindi utilizzata con Gambas: | Mostriamo di seguito un semplice esempio (in sistema a 64-bit), nel quale sarà creata una libreria dinamica condivisa esterna, contenente codice ''Assembly'', e sarà quindi utilizzata con Gambas: | ||
− | Private Extern Elabora( | + | Private Extern Elabora(valore As Integer) As Integer In "/tmp/C_Asm" |
Riga 76: | Riga 97: | ||
CreaSo() | CreaSo() | ||
− | i = | + | i = Elabora(160) |
Print i | Print i | ||
Riga 88: | Riga 109: | ||
"static int cbr asm(\"rbxregistro\");\n" & | "static int cbr asm(\"rbxregistro\");\n" & | ||
"static short cbr2 asm(\"rbxregistro2\");\n\n" & | "static short cbr2 asm(\"rbxregistro2\");\n\n" & | ||
− | "Elabora(int cbr_C) {\n\n" & | + | "int Elabora(int cbr_C) {\n\n" & |
"cbr=cbr_C;\n" & | "cbr=cbr_C;\n" & | ||
"cbr2 = 100;\n\n" & | "cbr2 = 100;\n\n" & | ||
Riga 101: | Riga 122: | ||
Shell "gcc -o /tmp/C_Asm.so /tmp/C_Asm.c -shared" Wait | Shell "gcc -o /tmp/C_Asm.so /tmp/C_Asm.c -shared" Wait | ||
+ | '''End''' | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==Uso della funzione ''__asm__()''== | ||
+ | Quest'altra modalità utilizza le risorse ''Assembly'' ugualmente tramite il codice C, ma fa uso della funzione ''__asm__()''. | ||
+ | |||
+ | Ne mostriamo un semplice esempio: | ||
+ | <FONT Color=gray>' ''int C_asm(int b)''</font> | ||
+ | Private Extern C_asm(valore As Integer) As Integer In "/tmp/C_asm" | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim i As Integer | ||
+ | |||
+ | Creaso() | ||
+ | |||
+ | i = C_asm(99) | ||
+ | |||
+ | Print "i = "; i | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure Creaso() | ||
+ | |||
+ | Dim s As String | ||
+ | |||
+ | s = "int C_asm(int b) {" & | ||
+ | "\n\n int a, c, d;" & | ||
+ | "\n\n __asm__(\"xor %%rax, %%rax;\"" & | ||
+ | "\n \"mov %%rbx, %%rax;\"" & | ||
+ | "\n \"inc %%rax;\"" & | ||
+ | "\n" & | ||
+ | "\n : \"=a\" (a)" & | ||
+ | "\n : \"b\" (b), \"c\" (c), \"d\" (d)" & | ||
+ | "\n );" | ||
+ | "\n\n}" | ||
+ | |||
+ | File.Save("/tmp/C_asm.c", s) | ||
+ | |||
+ | Shell "gcc -o /tmp/C_asm.so /tmp/C_asm.c -shared" Wait | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | ===Altri esempi particolari: effettuare un ciclo=== | ||
+ | Nel seguente esempio all'interno del codice ''Assembly'' verrà effettuato un ciclo. Ad ogni giro avverrà un operazione. Al termine del ciclo verrà restituito al codice C il valore finale dell'operazione, e quindi all'applicativo Gambas. | ||
+ | Private Extern C_Asm(bI As Integer, cI As Integer) As Integer In "/tmp/ciclo" | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim i As Integer | ||
+ | |||
+ | CreaSo() | ||
+ | |||
+ | i = C_Asm(1000000000, 2) | ||
+ | |||
+ | Print i | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure CreaSo() | ||
+ | |||
+ | File.Save("/tmp/ciclo.c", "int C_Asm(int b, int c) {" & | ||
+ | "\n\nint a, d;" & | ||
+ | "\n\n__asm__(\"xor %%eax, %%eax;\" /* Azzera il registro 'eax' */" & | ||
+ | "\n\"<FONT Color=#B22222>ciclo:</font> inc %%ecx;\" /* Ha inizio il ciclo e viene incrementato il registro 'ecx' di una unità */" & | ||
+ | "\n\"add %%ecx, %%eax;\" /* Si somma l'attuale valore del registro 'ecx' al valore del registro 'eax' */" & | ||
+ | "\n\"<FONT Color=#B22222>dec</font> %%ebx;\" /* Si decrementa il registro 'ebx' di una unità (quando avrà valore zero, si esce dal ciclo) */" & | ||
+ | "\n\"<FONT Color=#B22222>jne ciclo;</font>\" /* Salta alla riga ove è presente la parola 'ciclo': si compie un nuovo giro del ciclo */" & | ||
+ | "\n\n: \"=a\" (a)" & | ||
+ | "\n: \"b\" (b), \"c\" (c), \"d\" (d)" & | ||
+ | "\n);\n\n}") | ||
+ | |||
+ | Shell "gcc -o /tmp/ciclo.so /tmp/ciclo.c -shared" Wait | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | ===Altri esempi particolari: effettuare un'addizione=== | ||
+ | Nel seguente esempio all'interno del codice ''Assembly'' verrà effettuata una semplice addizione. Il risultato verrà restituito al codice C, e da esso all'applicativo Gambas. | ||
+ | Private Extern C_Asm(bI As Integer, cI As Integer) As Integer In "/tmp/addiz" | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim i As Integer | ||
+ | |||
+ | CreaSo() | ||
+ | |||
+ | i = C_Asm(1000000000, 2) | ||
+ | |||
+ | Print i | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure CreaSo() | ||
+ | |||
+ | File.Save("/tmp/addiz.c", "int C_Asm(int b, int c) {" & | ||
+ | "\n\nint a, d;" & | ||
+ | "\n\n__asm__(\"xor %%eax, %%eax;\" /* Azzera il registro 'eax' */" & | ||
+ | "\n\"add %%ebx, %%ecx;\" /* Si somma il valore del registro 'ebx' al valore del registro 'ecx' */" & | ||
+ | "\n\"mov %%ecx, %%eax;\" /* Si sposta il valore del registro 'ecx' nel registro 'eax', affinché venga restituito al codice C */" & | ||
+ | "\n\n: \"=a\" (a)" & | ||
+ | "\n: \"b\" (b), \"c\" (c), \"d\" (d)" & | ||
+ | "\n);\n\n}") | ||
+ | |||
+ | Shell "gcc -o /tmp/addiz.so /tmp/addiz.c -shared" Wait | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | ===Altri esempi particolari: effettuare una sottrazione=== | ||
+ | Nel seguente esempio all'interno del codice ''Assembly'' verrà effettuata una semplice sottrazione. Il risultato verrà restituito al codice C, e da esso all'applicativo Gambas. | ||
+ | Private Extern C_Asm(bI As Integer, cI As Integer) As Integer In "/tmp/sottr" | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim i As Integer | ||
+ | |||
+ | CreaSo() | ||
+ | |||
+ | i = C_Asm(1000000000, 2) | ||
+ | |||
+ | Print i | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure CreaSo() | ||
+ | |||
+ | File.Save("/tmp/sottr.c", "int C_Asm(int b, int c) {" & | ||
+ | "\n\nint a, d;" & | ||
+ | "\n\n__asm__(\"xor %%eax, %%eax;\" /* Azzera il registro 'eax' */" & | ||
+ | "\n\"sub %%ecx, %%ebx;\" /* Si sottrae il valore del registro 'ecx' al valore del registro 'ebx' */" & | ||
+ | "\n\"mov %%ebx, %%eax;\" /* Si sposta il valore del registro 'ebx' nel registro 'eax', affinché venga restituito al codice C */" & | ||
+ | "\n\n: \"=a\" (a)" & | ||
+ | "\n: \"b\" (b), \"c\" (c), \"d\" (d)" & | ||
+ | "\n);\n\n}") | ||
+ | |||
+ | Shell "gcc -o /tmp/sottr.so /tmp/sottr.c -shared" Wait | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | ===Altri esempi particolari: effettuare una moltiplicazione=== | ||
+ | Nel seguente esempio all'interno del codice ''Assembly'' verrà effettuata una semplice moltiplicazione. Il risultato verrà restituito al codice C, e da esso all'applicativo Gambas. | ||
+ | Private Extern C_Asm(bI As Integer, cI As Integer) As Integer In "/tmp/molti" | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim i As Integer | ||
+ | |||
+ | CreaSo() | ||
+ | |||
+ | i = C_Asm(1000000000, 2) | ||
+ | |||
+ | Print i | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure CreaSo() | ||
+ | |||
+ | File.Save("/tmp/molti.c", "int C_Asm(int b, int c) {" & | ||
+ | "\n\nint a, d;" & | ||
+ | "\n\n__asm__(\"xor %%eax, %%eax;\" /* Azzera il registro 'eax' */" & | ||
+ | "\n\"mov %%ecx, %%eax;\" /* Si sposta il valore del registro 'ecx' nel registro 'eax' */" & | ||
+ | "\n\"mul %%ebx;\" /* Si moltiplica il valore del registro 'ebx' per il valore del registro 'eax' */" & | ||
+ | "\n\"mov %%ebx, %%edx;\" /* Si sposta il valore del registro 'ebx' nel registro 'edx', affinché venga restituito al codice C */" & | ||
+ | "\n\n: \"=a\" (a)" & | ||
+ | "\n: \"b\" (b), \"c\" (c), \"d\" (d)" & | ||
+ | "\n);\n\n}") | ||
+ | |||
+ | Shell "gcc -o /tmp/molti.so /tmp/molti.c -shared" Wait | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | ===Altri esempi particolari: effettuare una divisione=== | ||
+ | Nel seguente esempio all'interno del codice ''Assembly'' verrà effettuata una semplice divisione. Il risultato verrà restituito al codice C, e da esso all'applicativo Gambas. | ||
+ | Private Extern C_Asm(bI As Integer, cI As Integer) As Integer In "/tmp/divis" | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim i As Integer | ||
+ | |||
+ | CreaSo() | ||
+ | |||
+ | i = C_Asm(2, 500) | ||
+ | |||
+ | Print i | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure CreaSo() | ||
+ | |||
+ | File.Save("/tmp/divis.c", "int C_Asm(int b, int c) {" & | ||
+ | "\n\nint a, d;" & | ||
+ | "\n\n__asm__(\"xor %%ax, %%ax;\" /* Azzera il registro 'ax' */" & | ||
+ | "\n\"mov %%cx, %%ax;\" /* Si sposta il valore del registro 'cx' nel registro 'ax' */" & | ||
+ | "\n\"div %%bl;\" /* Si divide il valore del registro 'cx' per il valore del registro 'bl' */" & | ||
+ | "\n\"mov %%bx, %%dx;\" /* Si sposta il valore del registro 'bx' nel registro 'dx', affinché venga restituito al codice C */" & | ||
+ | "\n\n: \"=a\" (a)" & | ||
+ | "\n: \"b\" (b), \"c\" (c), \"d\" (d)" & | ||
+ | "\n);\n\n}") | ||
+ | |||
+ | Shell "gcc -o /tmp/divis.so /tmp/divis.c -shared" Wait | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | ===Altri esempi particolari: passare una stringa di caratteri da far stampare in console/Terminale=== | ||
+ | Nel seguente esempio all'interno del codice ''Assembly'' verrà passata una stringa di caratteri da far stampare in console/Terminale. | ||
+ | Private Extern C_Asm(bI As Integer, cI As String) In "/tmp/stringa" | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim s As String | ||
+ | Dim i As Integer | ||
+ | |||
+ | CreaSo() | ||
+ | |||
+ | s = "testo qualsiasi\n" | ||
+ | |||
+ | i = Len(s) | ||
+ | |||
+ | <FONT Color=gray>' ''E' necessario passare anche la lunghezza della stringa da far stampare in console/Terminale:''</font> | ||
+ | C_Asm(i, s) | ||
+ | |||
+ | '''End''' | ||
+ | |||
+ | |||
+ | '''Private''' Procedure CreaSo() | ||
+ | |||
+ | File.Save("/tmp/stringa.c", "void C_Asm(int d, char * s) { // int d è la lunghezza della Stringa passata. E' imprescindibile !" & | ||
+ | "\n int a, b;" & | ||
+ | "\n\n __asm__(" & | ||
+ | "\n \"mov $4, %%eax;\"" & | ||
+ | "\n \"mov $1, %%ebx;\"" & | ||
+ | "\n \"int $0x80;\"" & | ||
+ | "\n \"mov $1, %%eax;\"" & | ||
+ | "\n \"mov $0, %%ebx;\"" & | ||
+ | "\n \"int $0x80;\"" & | ||
+ | "\n\n : \"=a\" (a)" & | ||
+ | "\n : \"b\" (b), \"c\" (s), \"d\" (d)" & | ||
+ | "\n );\n\n}") | ||
+ | |||
+ | Shell "gcc -o /tmp/stringa.so /tmp/stringa.c -shared" Wait | ||
+ | |||
'''End''' | '''End''' |
Versione attuale delle 17:57, 7 mag 2020
E' possibile inserire in una libreria esterna dinamica condivisa (.so), da noi realizzata, anche codice Assembly, al fine di ottenere prestazioni ancor più veloci.
In particolare sono possibili due modalità:
- con la funzione asm();
- con la funzione __asm__() .
Indice
- 1 Riepilogo schematico dei tipi di registri di memoria in base alla quantità di memoria resa da ciascuno disponibile
- 2 Uso della funzione asm()
- 3 Uso della funzione __asm__()
- 3.1 Altri esempi particolari: effettuare un ciclo
- 3.2 Altri esempi particolari: effettuare un'addizione
- 3.3 Altri esempi particolari: effettuare una sottrazione
- 3.4 Altri esempi particolari: effettuare una moltiplicazione
- 3.5 Altri esempi particolari: effettuare una divisione
- 3.6 Altri esempi particolari: passare una stringa di caratteri da far stampare in console/Terminale
Riepilogo schematico dei tipi di registri di memoria in base alla quantità di memoria resa da ciascuno disponibile
Di seguito mostriamo un breve e schematico ripilogo dei tipi di registri di memoria (registri del processore) utilizzabili nel linguaggio Assembly su un sistema a 64-bit in base alla quantità di memoria resa da ciascuno di essi disponibile:
================ rax (64 bit) ======== eax (32 bit) ==== ax (16 bit) == ah (8 bit) == al (8 bit)
o visto anche così:
|__64__|__56__|__48__|__40__|__32__|__24__|__16__|__8___| |__________________________RAX__________________________| | |____________EAX____________| | |_____AX______| | |__AH__|__AL__|
Uso della funzione asm()
Una prima modalità mostra come è possibile integrare il codice Assembly all'interno del linguaggio C in un sistema a 32-bit mediante la funzione asm():
static unsigned int car asm("raxregistro"); static unsigned int cbr asm("rbxregistro"); cbr = 15; asm("mov rbxregistro,%ax"); asm("mov %ax,raxregistro"); printf("%d",car);
alla fine, alla riga con printf, la variabile car avrà valore 15.
Problemi di compilazione nei sistemi a 64-bit durante la creazione di una Libreria .so
Si è riscontrato nei sistemi a 64-bit che durante la compilazione, qualora nel codice vi siano una o più variabili, viene restituito il seguente avviso di errore:
relocation R_X86_64_32S against `.bss' can not be used when making a shared object; recompile with -fPIC
Ciò avviene, ad esempio, nel tentativo di compilazione di un codice di questo tipo:
//libprova.c file: static unsigned int car asm("raxregistro"); static unsigned int cbr asm("rbxregistro"); int prova(int numero) { cbr=numero; asm("mov rbxregistro,%eax"); asm("ciclo:"); asm("dec %eax"); asm("jne ciclo"); asm("mov %eax,raxregistro"); return car; }
Il problema è nel trasferimento del valore contenuto nelle variabili "raxregistro" e "rbxregistro" alle righe appunto in Assembly:
asm ("mov rbxregistro, eax%"); asm("mov %eax,raxregistro");
e sembra essere legato alle differenze nel codice pic tra i386 e amd64.
Per risolvere il problema è necessario utilizzare uno spostamento relativo di indirizzo; altrimenti si finisce con il codice dipendente di posizione che non funziona per le librerie condivise.
Cosicché, data ad esempio le variabili "raxregistro" e "rbxregistro" in queste righe:
static unsigned int car asm("raxregistro"); static unsigned int cbr asm("rbxregistro");
per richiamarle bisogna usare l'address-relative, così:
asm("mov %eax,raxregistro(%rip)"); asm("mov rbxregistro(%rip),%eax");
Pertanto, l'esempio di codice, sopra mostrato, dovrà - per i sistemi a 64-bit - essere scritto come segue:
static unsigned int car asm("raxregistro"); static unsigned int cbr asm("rbxregistro"); int prova(int numero) { cbr=numero; asm("mov rbxregistro(%rip),%eax"); asm("ciclo:"); asm("dec %eax"); asm("jne ciclo"); asm("mov %eax,raxregistro(%rip)"); return car; }
Esempio pratico di creazione ed uso di una libreria dinamica condivisa, contenente codice Assembly, con Gambas
Mostriamo di seguito un semplice esempio (in sistema a 64-bit), nel quale sarà creata una libreria dinamica condivisa esterna, contenente codice Assembly, e sarà quindi utilizzata con Gambas:
Private Extern Elabora(valore As Integer) As Integer In "/tmp/C_Asm" Public Sub Main() Dim i As Integer CreaSo() i = Elabora(160) Print i End Private Procedure CreaSo() Dim s As String = "static unsigned int car asm(\"raxregistro\");\n" & "static int cbr asm(\"rbxregistro\");\n" & "static short cbr2 asm(\"rbxregistro2\");\n\n" & "int Elabora(int cbr_C) {\n\n" & "cbr=cbr_C;\n" & "cbr2 = 100;\n\n" & "asm(\"mov rbxregistro(%rip),%eax\");\n" & "asm(\"inc %eax\");\n" & "asm(\"add rbxregistro2(%rip), %eax\");\n" & "asm(\"mov %eax,raxregistro(%rip)\");" & "return car;\n\n}" File.Save("/tmp/C_Asm.c", s) Shell "gcc -o /tmp/C_Asm.so /tmp/C_Asm.c -shared" Wait End
Uso della funzione __asm__()
Quest'altra modalità utilizza le risorse Assembly ugualmente tramite il codice C, ma fa uso della funzione __asm__().
Ne mostriamo un semplice esempio:
' int C_asm(int b) Private Extern C_asm(valore As Integer) As Integer In "/tmp/C_asm" Public Sub Main() Dim i As Integer Creaso() i = C_asm(99) Print "i = "; i End Private Procedure Creaso() Dim s As String s = "int C_asm(int b) {" & "\n\n int a, c, d;" & "\n\n __asm__(\"xor %%rax, %%rax;\"" & "\n \"mov %%rbx, %%rax;\"" & "\n \"inc %%rax;\"" & "\n" & "\n : \"=a\" (a)" & "\n : \"b\" (b), \"c\" (c), \"d\" (d)" & "\n );" "\n\n}" File.Save("/tmp/C_asm.c", s) Shell "gcc -o /tmp/C_asm.so /tmp/C_asm.c -shared" Wait End
Altri esempi particolari: effettuare un ciclo
Nel seguente esempio all'interno del codice Assembly verrà effettuato un ciclo. Ad ogni giro avverrà un operazione. Al termine del ciclo verrà restituito al codice C il valore finale dell'operazione, e quindi all'applicativo Gambas.
Private Extern C_Asm(bI As Integer, cI As Integer) As Integer In "/tmp/ciclo" Public Sub Main() Dim i As Integer CreaSo() i = C_Asm(1000000000, 2) Print i End Private Procedure CreaSo() File.Save("/tmp/ciclo.c", "int C_Asm(int b, int c) {" & "\n\nint a, d;" & "\n\n__asm__(\"xor %%eax, %%eax;\" /* Azzera il registro 'eax' */" & "\n\"ciclo: inc %%ecx;\" /* Ha inizio il ciclo e viene incrementato il registro 'ecx' di una unità */" & "\n\"add %%ecx, %%eax;\" /* Si somma l'attuale valore del registro 'ecx' al valore del registro 'eax' */" & "\n\"dec %%ebx;\" /* Si decrementa il registro 'ebx' di una unità (quando avrà valore zero, si esce dal ciclo) */" & "\n\"jne ciclo;\" /* Salta alla riga ove è presente la parola 'ciclo': si compie un nuovo giro del ciclo */" & "\n\n: \"=a\" (a)" & "\n: \"b\" (b), \"c\" (c), \"d\" (d)" & "\n);\n\n}") Shell "gcc -o /tmp/ciclo.so /tmp/ciclo.c -shared" Wait End
Altri esempi particolari: effettuare un'addizione
Nel seguente esempio all'interno del codice Assembly verrà effettuata una semplice addizione. Il risultato verrà restituito al codice C, e da esso all'applicativo Gambas.
Private Extern C_Asm(bI As Integer, cI As Integer) As Integer In "/tmp/addiz" Public Sub Main() Dim i As Integer CreaSo() i = C_Asm(1000000000, 2) Print i End Private Procedure CreaSo() File.Save("/tmp/addiz.c", "int C_Asm(int b, int c) {" & "\n\nint a, d;" & "\n\n__asm__(\"xor %%eax, %%eax;\" /* Azzera il registro 'eax' */" & "\n\"add %%ebx, %%ecx;\" /* Si somma il valore del registro 'ebx' al valore del registro 'ecx' */" & "\n\"mov %%ecx, %%eax;\" /* Si sposta il valore del registro 'ecx' nel registro 'eax', affinché venga restituito al codice C */" & "\n\n: \"=a\" (a)" & "\n: \"b\" (b), \"c\" (c), \"d\" (d)" & "\n);\n\n}") Shell "gcc -o /tmp/addiz.so /tmp/addiz.c -shared" Wait End
Altri esempi particolari: effettuare una sottrazione
Nel seguente esempio all'interno del codice Assembly verrà effettuata una semplice sottrazione. Il risultato verrà restituito al codice C, e da esso all'applicativo Gambas.
Private Extern C_Asm(bI As Integer, cI As Integer) As Integer In "/tmp/sottr" Public Sub Main() Dim i As Integer CreaSo() i = C_Asm(1000000000, 2) Print i End Private Procedure CreaSo() File.Save("/tmp/sottr.c", "int C_Asm(int b, int c) {" & "\n\nint a, d;" & "\n\n__asm__(\"xor %%eax, %%eax;\" /* Azzera il registro 'eax' */" & "\n\"sub %%ecx, %%ebx;\" /* Si sottrae il valore del registro 'ecx' al valore del registro 'ebx' */" & "\n\"mov %%ebx, %%eax;\" /* Si sposta il valore del registro 'ebx' nel registro 'eax', affinché venga restituito al codice C */" & "\n\n: \"=a\" (a)" & "\n: \"b\" (b), \"c\" (c), \"d\" (d)" & "\n);\n\n}") Shell "gcc -o /tmp/sottr.so /tmp/sottr.c -shared" Wait End
Altri esempi particolari: effettuare una moltiplicazione
Nel seguente esempio all'interno del codice Assembly verrà effettuata una semplice moltiplicazione. Il risultato verrà restituito al codice C, e da esso all'applicativo Gambas.
Private Extern C_Asm(bI As Integer, cI As Integer) As Integer In "/tmp/molti" Public Sub Main() Dim i As Integer CreaSo() i = C_Asm(1000000000, 2) Print i End Private Procedure CreaSo() File.Save("/tmp/molti.c", "int C_Asm(int b, int c) {" & "\n\nint a, d;" & "\n\n__asm__(\"xor %%eax, %%eax;\" /* Azzera il registro 'eax' */" & "\n\"mov %%ecx, %%eax;\" /* Si sposta il valore del registro 'ecx' nel registro 'eax' */" & "\n\"mul %%ebx;\" /* Si moltiplica il valore del registro 'ebx' per il valore del registro 'eax' */" & "\n\"mov %%ebx, %%edx;\" /* Si sposta il valore del registro 'ebx' nel registro 'edx', affinché venga restituito al codice C */" & "\n\n: \"=a\" (a)" & "\n: \"b\" (b), \"c\" (c), \"d\" (d)" & "\n);\n\n}") Shell "gcc -o /tmp/molti.so /tmp/molti.c -shared" Wait End
Altri esempi particolari: effettuare una divisione
Nel seguente esempio all'interno del codice Assembly verrà effettuata una semplice divisione. Il risultato verrà restituito al codice C, e da esso all'applicativo Gambas.
Private Extern C_Asm(bI As Integer, cI As Integer) As Integer In "/tmp/divis" Public Sub Main() Dim i As Integer CreaSo() i = C_Asm(2, 500) Print i End Private Procedure CreaSo() File.Save("/tmp/divis.c", "int C_Asm(int b, int c) {" & "\n\nint a, d;" & "\n\n__asm__(\"xor %%ax, %%ax;\" /* Azzera il registro 'ax' */" & "\n\"mov %%cx, %%ax;\" /* Si sposta il valore del registro 'cx' nel registro 'ax' */" & "\n\"div %%bl;\" /* Si divide il valore del registro 'cx' per il valore del registro 'bl' */" & "\n\"mov %%bx, %%dx;\" /* Si sposta il valore del registro 'bx' nel registro 'dx', affinché venga restituito al codice C */" & "\n\n: \"=a\" (a)" & "\n: \"b\" (b), \"c\" (c), \"d\" (d)" & "\n);\n\n}") Shell "gcc -o /tmp/divis.so /tmp/divis.c -shared" Wait End
Altri esempi particolari: passare una stringa di caratteri da far stampare in console/Terminale
Nel seguente esempio all'interno del codice Assembly verrà passata una stringa di caratteri da far stampare in console/Terminale.
Private Extern C_Asm(bI As Integer, cI As String) In "/tmp/stringa" Public Sub Main() Dim s As String Dim i As Integer CreaSo() s = "testo qualsiasi\n" i = Len(s) ' E' necessario passare anche la lunghezza della stringa da far stampare in console/Terminale: C_Asm(i, s) End Private Procedure CreaSo() File.Save("/tmp/stringa.c", "void C_Asm(int d, char * s) { // int d è la lunghezza della Stringa passata. E' imprescindibile !" & "\n int a, b;" & "\n\n __asm__(" & "\n \"mov $4, %%eax;\"" & "\n \"mov $1, %%ebx;\"" & "\n \"int $0x80;\"" & "\n \"mov $1, %%eax;\"" & "\n \"mov $0, %%ebx;\"" & "\n \"int $0x80;\"" & "\n\n : \"=a\" (a)" & "\n : \"b\" (b), \"c\" (s), \"d\" (d)" & "\n );\n\n}") Shell "gcc -o /tmp/stringa.so /tmp/stringa.c -shared" Wait End