linguaggio assembly

rctimelines

Utente Èlite
5,144
2,023
CPU
Ryzen 7 2700X | i7-6700k@4.5 | i5-4460... altri
Dissipatore
wraith MAX | Scythe Katana2|Arctic Freezer 11LP
Scheda Madre
Asrock B450 Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
HDD
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
GPU
RadeonPro WX3100 4G | ZOTAC GTX 1070 8G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | LG Ultrawide 27''
Net
fibra 1000
OS
Windows10-pro64/OpenSUSE-QL15.1/Debian 10.3
stai già andando su cose più difficili per un neofita.. e anche da spiegare in questo contesto.

Intanto MIPS sono processori RISC per cui il numero di opcode è inferiore rispetto ai CISC,
l'istruzione che dici ha lunghezza fissa di 32 bit di cui i primi 6 individuano il tipo di istruzione (opcode) mentre i restanti bit hanno significati diversi in base all'istruzione chiamata.
Però, sinceramente, inizierei a considerare sistemi più semplici.

Inviato dal mio Nexus 6P utilizzando Tapatalk
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,853
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
L'ISA è ciò che tu vedi, ciò che ti viene messo a disposizione. L'ISA definisce il tipo di istruzioni, di operazioni che puoi compiere (anche la lunghezza delle istruzioni).

L'opcode in sè definisce il tipo di operazione (OPcode, Operation Code). Detto un pò brutalmente "spostamento", "somma", sottrazione"...
Sono solo uno dei campi che compongono l'istruzione. In realtà è un pò più complesso, nel senso che alcuni bit (1, in particolare, chiamato "w") consentono di individuare l'ampiezza degli operandi. A questo seguono altri campi, come mod_reg_rm, che identifica il tipo degli operandi (registro, memoria) e altri campi ancora.

Più a basso livello, come microcodice, il discorso cambia; l'implementazione esatta non mi sembra sia pubblica, si dovrebbe reversare.

Ad ogni modo, rimanendo ad un livello più alto, avevo mostrato come sono codificate le istruzioni in 8086 in questo articolo https://forum.tomshw.it/threads/il-linguaggio-macchina-del-8086.580474/
Ci sono esempi di vario tipo più sotto (parte 2).

Uno degli esempi che riporto per Intel 8086, ad esempio è:

Codice:
00100110 10001001 00011110 00101101 00000001

che codifica un'istruzione mov [ES:012Dh], bx.

un ultima cosa poi non rompo più:
ho visto per esempio che gli opcode nell'architettura MIPS sono a 6bit..


cio vuol dire che a livello fisico ogni 6 bit ce qualche componente elettronico che "switcha" per proseguire e specificare rs,rt, address ecc.. ? o ciò avviene ancora a livello software e non tanto "elettronico" ?

p.s ce differenza tra isa e microcodice?queste possono essere considerte parte del firmware di una cpu giusto?

Evito di risponderti sui dettagli di MIPS, non conoscendolo.
Tra ISA e microdice c'è differenza, poichè come dicevo sopra, il livello ISA è quello che viene esposto. Il microcodice non lo vedi (tipicamente viene aggiornato dal produttore, eg. Intel). Il microcodice è ciò che ci sta sotto: intel è una CISC (Complex Instruction Set Computer), ma internamente viene di fatto utilizzato RISC (con il microcodice).
Di fatto l'update al microcodice è l'update al firmware.

EDIT:
Ho trovato questa bella "discussione", che potrebbe interessare altri: https://security.stackexchange.com/...ssor-microcode-manipulation-to-change-opcodes
 
  • Mi piace
Reazioni: rob25111

rob25111

Nuovo Utente
38
0
quindi diciamo che l'ISA è ciò che io posso "manipolare e mi viene messo a disposizione" mentre il microcodice ha a che fare con l'architettura ancora più fisica della cpu.. una sorta di "ISA" ancora più primitive giusto ? (in senso lato giusto per crearmi un immagine mentale)

opcode puo essere invece considerato come "parte integrante delle ISA" ? nel senso che è quindi gestito dal microcodice dopo la conversione dall' ASCII dell'ISA ?
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,853
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
L'ISA comprende il tipo di istruzioni: di fatto l'opcode è il tipo di istruzione (somme, sottrazioni, assegnamenti... ma anche i salti condizionali ad esempio). Quindi si che è parte dell'ISA (è il tipo di operazione).
Il microcodice è interno, non hai a che fare direttamente con quello. Quindi se per "architettura ancora più fisica" intendi questo... diciamo di si (sta comunque ad un livello più basso, primitivo, mettiamola così).
Non so cosa intendi con "ASCII dell'ISA"... tecnicamente è errato, non ha un significato.
 
  • Mi piace
Reazioni: rob25111

rctimelines

Utente Èlite
5,144
2,023
CPU
Ryzen 7 2700X | i7-6700k@4.5 | i5-4460... altri
Dissipatore
wraith MAX | Scythe Katana2|Arctic Freezer 11LP
Scheda Madre
Asrock B450 Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
HDD
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
GPU
RadeonPro WX3100 4G | ZOTAC GTX 1070 8G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | LG Ultrawide 27''
Net
fibra 1000
OS
Windows10-pro64/OpenSUSE-QL15.1/Debian 10.3
Io credo sinceramente che stiamo andando fuori strada e trattare questi argomenti in una modalità da "chiacchiera da bar" rischia solo di creare grande confusione nell'OP e portarlo a dei concetti errati che poi compromettono la comprensione di tutto.

La tua domanda originaria riguardava l'assembly e scrivere codice macchina senza "compilatore".

Poi ti sei fossilizzato sul concetto di ISA a cui abbiamo aggiunto gli opcode e il microcosice.. Ma mi pare che adesso ti stai inoltrando in libere interpretazioni filosofiche di tutto ciò.
Siccome sono aspetti tecnici ben definiti su cui, nel tempo, è sono stati scritti volumi di letteratura tecnica, forse non è il caso che in questo contesto di un forum cerchiamo di spiegarti il tutto con qualche breve post e pretendiamo che tu abbia tutto chiaro.

Quello che interessa a te è adesso, a differenza della domanda iniziale del thread, è conoscere l'architettura dei processori: il consiglio che posso rinnovarti è quello di studiare su libri ma a partire da sistemi piuttosto semplici e primitivi (no l'architettura MIPS o SPARC) altrimenti si inseriscono già subito ulteriori concetti che complicano ulteriormente il discorso.

Inviato dal mio Nexus 6P utilizzando Tapatalk
 

pabloski

Utente Èlite
2,868
916
quindi diciamo che l'ISA è ciò che io posso "manipolare e mi viene messo a disposizione"

Perchè fissarsi con l'ISA? Alla fin fine è solo un'etichetta che viene data all'insieme di tutte le istruzioni che il programmatore può usare per programmare il processore.

il microcodice ha a che fare con l'architettura ancora più fisica della cpu

Ha a che fare con la parte più fisica di una CPU, ma per un motivo ben preciso. Quando nacquero i processori CISC, tipo gli x86 che usiamo nei PC, il set d'istruzioni ( complesso rispetto ai RISC ) era comunque gestibile. Gestibile in senso elettronico. Cioè era ancora umano realizzare circuiti che mappavano quelle istruzioni, cioè che implementavano fisicamente le istruzioni contenute nell'ISA.

Il problema è che si arrivò ad un tempo in cui l'elettronica era assurdamente complessa, piena di bug e criminalmente inefficiente. E fu allora che i capoccioni che lavorano allo sviluppo delle CPU pensarono di scorporare l'ISA dal processore ( la parte elettronica ) sottostante.

Cioè, se tu prendi un Core i7, elettronicamente parlando non è un x86. E' una CPU che implementa un'insieme di istruzioni particolari, ma comunque non quelle che tu programmatore vedi. Chi si occupa di trasformare le istruzioni dell'ISA in sequenze di istruzioni del processore, è appunto il microcodice. Alla fin fine il microcodice è una libreria piena di procedure. E queste procedure sono le istruzioni dell'ISA. Il codice scritto in queste procedure è il codice macchina del processore reale. Tutto quest'ambaradan, perchè l'architettura CISC stava facendo naufragare l'intera industria microelettronica, con la sua complessità ed ingestibilità.

opcode puo essere invece considerato come "parte integrante delle ISA" ?

L'opcode è il pezzettino d'istruzione che indica l'operazione. La restante parte serve per specificare il tipo, il numero e altre cose, riguardo gli operandi.

Ti basta guardare un qualsiasi manuale x86 e noterai subito che ci sono scritte cose tipo "10010r/w...operando immediato...blahblah". Quel r/w ti dice che lì c'è un bit che specifica se l'operazione è di tipo read o write. Operando immediato ti consente di specificare il dato direttamente nella stringa che codifica l'istruzione. E' solo un esempio. Si possono specificare un sacco di cose, che dipendono dall'istruzione. Ci sono pure istruzioni che hanno solo l'opcode.
 
  • Adoro
Reazioni: rob25111
U

Utente 16812

Ospite
LINGUAGGIO ASSEMBLY (prima parte)
--------------------------------------------------------------

ho una curiosità.
il linguaggio assembly è il linguaggio più vicino possibile al linguaggio macchina.
...ma puo essere comunque considerato un "linguaggio alto" in quanto non si scrive mica in 1-0 (binario)
la macchina deve comunque avere un compilatore giusto?
mettiamo che io ho un pc anni 80 e non ho internet per scaricare un compilatore..
come faccio a "programmarne uno?"
nel senso come si crea il compilatore di un linguaggio cosi basso?

Non è proprio così, i linguaggi di programmazione sono ad alto livello (a ciascuna istruzione corrispondono più istruzioni macchina, ossia le istruzioni non dipendono dal processore), il linguaggio Assembler è a basso livello (ciascuna istruzione Assembler corrisponde ad una istruzione macchina, esattamente come il linguaggio macchina l'Assembler dipende dal processore) :sisi:
La differenza sta nel fatto che l'Assembler rende più facile la programmazione in quanto vengono utilizzati dei "nomi simbolici" sia per i codici operativi che per le locazioni di memoria (in cui risiedono i dati).
Gli indirizzi vengono calcolati automaticamente dall'assemblatore durante la fase di traduzione del programma.
Il programma che è in grado di tradurre un "sorgente" in linguaggio Assembler in un programma "oggetto" in linguaggio macchina si chiama "assemblatore".
L'assemblatore opera con una doppia "passata": dapprima controlla la sintassi e produce la cosiddetta "tabella dei simboli" (se vengono riscontrati errori in questa fase, il lavoro dell'assemblatore si interrompe con la segnalazione degli errori stessi), poi esegue la traduzione vera e propria (usando la tabella dei simboli), generando il codice oggetto.
Ora però c'è qualcosa in più da illustrare e al momento non ho tempo, devo scappare, in seguito faremo qualche esempio in Z80.
Ciao, a dopo ;)
 
Ultima modifica da un moderatore:
  • Mi piace
Reazioni: rob25111

rob25111

Nuovo Utente
38
0
grazie mille a tutti! quantomeno inizio a crearmi un immagine mentale.
potete consigliarmi qualche libro che mi chiarisca tutte queste idee?

p.s
attendo @gronag per qualche esempio :D
 

pabloski

Utente Èlite
2,868
916
potete consigliarmi qualche libro che mi chiarisca tutte queste idee?

Molto vecchio ma molto buono "Programming the 8086/8088" di James Coffron.

La parte veramente ottima è la sezione che elenca tutte le istruzioni x86, la loro traduzione in binario, come calcolare i vari campi che affiancano l'opcode.

Descrive ovviamente i vecchi processori 8086 e 8088, quindi nemmeno il 286. Per questo dicevo che è vecchio. Ma spiega molte cose, in modo molto chiaro.

Da lì si può poi approfondire le novità introdotte nella famiglia x86.
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,853
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
A questo punto un ottimo testo può anche essere "The art of assembly language": http://www.plantation-productions.com/Webster/www.artofasm.com/index.html
Valgono le considerazioni esposte da Pabloski comunque, si tratta di un vecchio libro, e tante cose che vedrai oggi non valgono più (o non sono più utilizzate).

Se cerchi in rete trovi la lista di opcode, ma molti trattano x86/x64.
Su questo PDF, verso le ultime pagine, trovi l'istruzione (lo mnemonico) e la relativa rappresentazione in binario: http://www.mediafire.com/download/u4aa3ry00j1545r/231455.zip


PS. @pabloski solo una piccola nota, inutile lo so, ma per precisione: il bit denominato "w" nell'opcode non sta a significare "write" ma indica la dimensione dell'operando (con 8086 -> 8/16bit).
Mi riferisco a:

Ti basta guardare un qualsiasi manuale x86 e noterai subito che ci sono scritte cose tipo "10010r/w...operando immediato...blahblah". Quel r/w ti dice che lì c'è un bit che specifica se l'operazione è di tipo read o write.
 
U

Utente 16812

Ospite
LINGUAGGIO ASSEMBLY (seconda parte)
------------------------------------------------------------------

grazie mille a tutti! quantomeno inizio a crearmi un immagine mentale.
potete consigliarmi qualche libro che mi chiarisca tutte queste idee?

p.s
attendo @gronag per qualche esempio :D

Eccomi, sono tornato, prima di parlare del calcolo degli indirizzi occorre ricordare che la traduzione in linguaggio macchina riguarda solamente le istruzioni "esecutive", ossia quelle corrispondenti alle istruzioni macchina :sisi:
Ora, le istruzioni possono essere anche "dichiarative" e "direttive" :asd:
Le istruzioni dichiarative e direttive non corrispondono ad istruzioni in linguaggio macchina; attraverso un'istruzione dichiarativa si può fare riferimento ad un dato mediante un nome, senza conoscerne l'indirizzo, mentre una direttiva fornisce delle indicazioni all'assemblatore, il quale si incarica di seguirle durante la fase di traduzione.
Come fa l'assemblatore a calcolare gli indirizzi ?
Qui c'è un'ulteriore difficoltà poiché il calcolo degli indirizzi dipende dal "modello" di memoria adottato dal microprocessore :asd:
Esistono due tipi di modello di memoria: quello "contiguo" e quello "segmentato" (ad es. le CPU Intel X86 usano il modello a memoria segmentata).
Senza entrare in dettagli che appesantirebbero inutilmente la trattazione, diciamo che la memoria di programma viene chiamata "spazio logico" e gli indirizzi sono chiamati "logici".
Se lo spazio logico è diverso dallo "spazio fisico", in cui il programma viene eseguito, il codice dovrà essere "rilocabile".
Ecco che entra in gioco il "linker", il quale trasforma il codice oggetto in codice eseguibile.
In pratica l'eseguibile (lo spazio logico) può risiedere in un file memorizzato su un drive ma al momento dell'esecuzione il programma deve essere "spostato" in uno spazio fisico (in memoria centrale).
Facendo questa distinzione tra spazio fisico e spazio logico, il caricamento del programma avviene in modo "dinamico" (come accade ad esempio nel caso delle librerie DLL di Windows).
La "rilocazione" consiste proprio nel sostituire un indirizzo fisico a ciascun indirizzo logico.
A presto ;)

P.S. Gli indirizzi usati dal microprocessore 8086, del tipo segment:offset, sono effettivamente rilocabili: l'offset rappresenta la distanza rispetto al segmento iniziale, il registro di segmento contiene l'indirizzo iniziale di ciascun segmento, per cui sommando l'indirizzo del segmento d'inizio con l'offset si ottiene l'indirizzo voluto :asd:
 
Ultima modifica da un moderatore:

rctimelines

Utente Èlite
5,144
2,023
CPU
Ryzen 7 2700X | i7-6700k@4.5 | i5-4460... altri
Dissipatore
wraith MAX | Scythe Katana2|Arctic Freezer 11LP
Scheda Madre
Asrock B450 Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
HDD
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
GPU
RadeonPro WX3100 4G | ZOTAC GTX 1070 8G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | LG Ultrawide 27''
Net
fibra 1000
OS
Windows10-pro64/OpenSUSE-QL15.1/Debian 10.3
Bene.. quindi? Mi pare che qui il discorso travalichi ulteriormente il quesito iniziale. Personalmente non avevo capito che all'OP interessasse l'indirizzamento da parte dell'assembler.
D'altra parte, nelle CPU più semplici, che secondo me dovrebbero essere prese in considerazione per spiegare ciò che viene chiesto, l'assemblatore non calcola gli indirizzi perché le modalità di indirizzamento sono intrinseche al processore, che offre specifiche varianti delle stesse istruzioni.. ognuna individuata, appunto, da un diverso opcode.

Inviato dal mio Nexus 6P utilizzando Tapatalk
 

Andretti60

Utente Èlite
6,440
5,091
ho una curiosità.
il linguaggio assembly è il linguaggio più vicino possibile al linguaggio macchina.
...ma puo essere comunque considerato un "linguaggio alto" in quanto non si scrive mica in 1-0 (binario)
Si e no. Vero che non si programma scrivendo numeri bensì “simboli mnemonici”, ma è vero che ogni istruzione scritta in simboli viene concertita in una istruzione (ossia un numero binario) che la CPU è capace di eseguire.
la macchina deve comunque avere un compilatore giusto?
...
Anche qui, si e no.
Vedi, la CPU in realtà è formata da diversi componenti, il “cuore” è la ALU ossia la unità logico/matematica capace di eseguire le operazioni.
Quando un programma viene eseguito, le singole istruzioni arrivano in sequenza alla ALU, che le esegue se ovviamente sono istruzioni valide. Scrivere istruzioni in binario è estremamente complesso, per questo si programma in Assembly, ossia usando “simboli”, l’assemblatore legge tali simboli, e controlla se sono validi, se lo sono vengono convertiti in “linguaggio macchina” (ossia in binario) altrimenti dà un messaggio di errore. Il modulo generato (ossia l’insieme di numeri binari) viene chiamato “eseguibile”.

Nota bene: questo è sommario estremamente semplificato. Moderne CPU sono ormai molto più complesse, ma l’idea di base è la stessa.
 
U

Utente 16812

Ospite
LINGUAGGIO ASSEMBLY (terza e ultima parte)
--------------------------------------------------------------------------

Ciascuna CPU possiede un suo proprio "set" di istruzioni; ciascuna istruzione è formata da un codice operativo (di solito in esadecimale) e da un simbolo "mnemonico" che richiama l'operazione che s'intende realizzare.
Ogni mnemonico è composto da due campi separati: 1) il primo descrive l'operazione da svolgere; 2) il secondo rappresenta l'operando che contiene i dati.
Facciamo un esempio con lo Z80, un microprocessore a 8-bit tuttora utilizzato in semplici controlli di processo e nelle calcolatrici Texas Instruments della serie TI-83/TI-84: consideriamo il mnemonico LD A,(HL).
L'operazione è LD (spostamento dei dati), l'operando è A,(HL).
L'istruzione opera lo spostamento del dato contenuto nella locazione di memoria puntata dal registro HL nel registro accumulatore A.
Ora, come abbiamo già detto, gli "statement" possono essere esecutivi, dichiarativi o direttivi ma fondamentale è la sintassi di scrittura di tali "statement".
Ciascuno statement (ossia ciascuna riga di programma) è suddiviso in 3 campi: 1) il campo "label" (l'etichetta); 2) il campo istruzione (il mnemonico, visto sopra); 3) il campo di commento.
Vediamo un esempio: SPOSTA LD A,(HL) ;sposta il dato contenuto in HL nell'accumulatore A.
SPOSTA rappresenta l'etichetta associata all'indirizzo di "allocazione" dell'istruzione (in questo modo è possibile utilizzare l'etichetta in sostituzione dell'indirizzo di allocazione del mnemonico).
LD A,(HL) è l'istruzione, che dovrà essere presente nel set di istruzioni del microprocessore per cui si sta scrivendo il programma.
Il campo di commento è opzionale e l'assemblatore ignora tutto ciò che viene scritto dopo il punto e virgola, in pratica il suo scopo è quello di documentare il programma e nell'Assembly è fondamentale.
Termina qui questa breve "digressione" sul linguaggio Assembly, ulteriori spiegazioni potranno essere fornite solo dopo aver descritto l'architettura dei microprocessori, mi auguro di aver dato una risposta, anche parziale, alle domande espresse dall'apertore del thread.
A presto ;)

P.S. Un programma in Assembly può essere scritto con qualsiasi editor di testo in formato ASCII (con estensione .asm).
Solitamente per l'8086 noi utilizziamo il TASM (il Turbo Assembler) della Borland (eventualmente emulato in DOSBox) e il MASM (il Macro Assembler) della Microsoft (la versione per CPU Intel X64 è contenuta in Visual Studio/Visual C++) ;)
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili