di  -  giovedì 18 Luglio 2013

Torniamo a questa serie di articoli, che è rimasta da troppo tempo nel cassetto, ma che merita di essere conclusa con le ultime parti. In questo, in particolare, analizzeremo le statistiche relative al numero degli argomenti di un’istruzione, che sono messi in relazione con le varie modalità d’indirizzamento.

Come sappiamo, ogni istruzione può avere un numero variabile di argomenti, da nessuno fino a un massimo di 4 (per alcune istruzioni AVX; l’ultima estensione SIMD di Intel). Ogni argomento non può essere di qualunque tipo, ma esistono delle regole ben precise. Ad esempio può esserci un solo valore immediato, se è presente. Oppure può esserci un solo operando che punta a una locazione di memoria.

In realtà esistono delle pregevoli eccezioni, che sono rappresentate dalle istruzioni cosiddette di “stringa” (di cui abbiamo discusso nella serie di articoli sull’aspetto “legacy” di x86), che possono anche operare contemporaneamente con due locazioni di memoria, oppure con una locazione di memoria e una porta di I/O (che, in realtà, rimane pur sempre una memoria esterna al processore).

La libreria (diStorm3) per disassemblare codice x86/x64 che ho usato per generare le statistiche restituisce in questi casi due argomenti per le istruzioni, e nel caso di un riferimento alla memoria riporta il classico indirizzamento indicizzato, facendo uso del registro SI e/o DI.

In realtà è bene precisare che queste istruzioni sono riportate senza operandi nei manuali di Intel e AMD, in quanto il meccanismo di utilizzo dei registri e dell’indirizzamento della memoria è implicito nella medesima istruzione.

Quella operata da diStorm3 è, pertanto, una scelta arbitraria, ma risulta comunque comoda perché fa capire che per quelle istruzioni viene in ogni caso eseguito un accesso in memoria con una determinata modalità.

Ciò detto, analizziamo la distribuzione delle varie combinazioni di argomenti riscontrati per x86, ricorrendo, al solito, alla beta pubblica di Adobe Photoshop CS6 a 32 bit (PS32):

Operands                                      Count
REG,[REG+DISP]                               379139
REG                                          297616
PC                                           252353
REG,REG                                      198565
[REG+DISP],REG                               145407
REG,IMM                                       99129
IMM                                           80916
[REG+DISP],IMM                                71467
[REG+DISP]                                    57483
REG,[REG+REG*SC+DISP]                         36837
FPU                                           17887
REG,[DISP]                                    16086
[DISP],REG                                    15417
FPU,FPU                                       11872
[REG+REG*SC+DISP]                             10322
[DISP]                                         8928
[REG+REG*SC+DISP],REG                          5537
HREG,IMM                                       3661
[DISP],IMM                                     1634

Ero indeciso se riportare meno dati per non allungare troppo la tabella, ma poi ho preferito prendere i primi 20 anziché i primi 10 o 15, perché emerge qualche dato interessante fra gli ultimi, non tanto per la frequenza, che ovviamente risulta piuttosto bassa (basti vedere i numeri dei primi 10), quanto per la tipologia degli argomenti.

Leggendo il primo numero si potrebbe arrivare alla classica conclusione che… ci troviamo di fronte a un CISC. Infatti abbondano i riferimenti alla memoria, e questo si verifica anche in altri casi.

In realtà quando analizzeremo l’elenco delle istruzioni (sotto forma di mnemonici), nel prossimo articolo della serie, vedremo che la situazione non è esattamente come potrebbe sembrare a primo acchito, guardando soltanto alla tipologia degli operandi. Un po’ di pazienza, pertanto, e il quadro sarà molto più chiaro.

Dai primi 5 risultati, che dominano l’intero panorama, emerge un quadro abbastanza chiaro. Innanzitutto le operazioni che leggono dalla memoria (prima posizione) sono più del doppio rispetto a quelle che vi scrivono (quinta posizione).

In mezzo troviamo operazioni coi registri, rispettivamente con uno solo (seconda posizione), presumibilmente a causa dell’ABI di x86, che fa abbondante uso di PUSH e POP dei registri (ma anche l’uso di un valore immediato, IMM, che è in settima posizione, è spiegabile con PUSH di valori immediati), e poi con due registri (quarta posizione).

In terza posizione si collocano le istruzioni che fanno uso di salti relativi, che vedremo essere incarnati dalle istruzioni CALL, JMP, e Jcc (salto su condizione).

Gettando lo sguardo un po’ più in basso, appare finalmente qualche istruzione/modalità squisitamente CISC. Mi riferisco in particolare a [REG+DISP],IMM, il cui scopo è utilizzare un valore immediato (come sorgente) e in una locazione di memoria (in genere come seconda sorgente, ma anche come destinazione).

Infatti ciò non trova riscontro in una macchina RISC, in quanto per realizzare la medesima operazione sarebbe necessaria almeno un’istruzione per caricare il valore immediato in un registro (ma soltanto nei casi più semplici, con valori immediati piccoli o comunque appartenenti a un insieme ristretto), e un’altra per memorizzarlo successivamente in memoria. Questo nel caso più semplice di una semplice MOVE; con istruzioni più complesse (ad esempio una ADD) servirebbe anche una lettura dell’operando dalla memoria.

Il tutto, quindi, sporcando un registro e aggiungendo una dipendenza nella pipeline. Questo perché la store dipende dalla precedente MOVE col valore immediato. Esistono, comunque, tecniche di propagazione del valore che potrebbero evitare questa dipendenza.

Tornando alle statistiche, più rare sono le modalità d’indirizzamento complesse, come [REG+REG*SC+DISP], che non tutti i RISC supportano proprio a motivo della loro complessità, ma questo era già emerso dalla precedente analisi incentrata sulle singole modalità d’indirizzamento della memoria.

E’ interessante, invece, notare che queste riguardano per lo più la lettura verso la memoria, mentre la scritture risultano di gran lunga meno frequenti, come pure l’uso in istruzioni che adoperano un solo argomento di questo tipo.

Molto rara, ma pur sempre presente, è l’uso dell’FPU, in particolare con un solo registro; oppure, un po’ meno frequente, con una coppia di registri dell’unità x87.

Singolare, invece, è l’accesso diretto alla memoria, quindi senza far uso di registri, che è rappresentato dall’etichetta [DISP]. Si potrebbe pensare a un eccessivo utilizzo di variabili globali (che nel buon codice dovrebbero essere usate il meno possibile), ma anche qui il motivo principale verrà fuori nell’ultimo articolo della serie, quando andremo a vedere i numeri degli aspetti “legacy” di quest’architettura.

Verso la fine salta fuori un altro aspetto “legacy” di x86, che riguarda la presenza di registri “alti” (AH, BH, ecc.) a 8 bit, che sono stati etichettati come HREG. Il loro uso è sporadico, perché si tratta di un’ottimizzazione (la possibilità di accedere agli 8 bit alti dei primi 4 registri general purpose) ormai in disuso, anche perché potrebbe creare problemi con l’implementazione (l’accesso parziale a un registro).

Arriva finalmente il momento di dare un’occhiata ai numeri di x64, grazie alla beta pubblica di Adobe Photoshop CS6 a 64 bit (PS64):

Operands                                      Count
REG,[REG+DISP]                               427264
REG,REG                                      313662
PC                                           285434
[REG+DISP],REG                               192774
REG,IMM                                      119497
REG                                          105832
REG,[REG+REG*SC+DISP]                         55623
[REG+DISP],IMM                                49858
SSE,SSE                                       40482
SSE,[REG+DISP]                                22811
[REG+DISP]                                    17786
[REG+DISP],SSE                                12397
[REG+REG*SC+DISP],REG                         11685
SSE,[REG+REG*SC+DISP]                          8711
[REG+REG*SC+DISP],SSE                          5982
[REG+REG*SC+DISP]                              4221
[REG+REG*SC+DISP],IMM                          2493
REG,REG,IMM                                    2163
SSE,REG                                        2162

La lettura delle prime 6 posizioni va fatta sempre in ottica dell’ABI, che è cambiata rispetto a x86. Adesso sono disponibili molti più registri, per cui sono richiesti meno caricamenti di dati dalla memoria, e quind si fa più uso dei registri (ecco perché REG,REG è balzato al secondo posto). Inoltre le PUSH e le POP sono di gran lunga inferiori, e ciò spiega il netto calo dell’uso di un solo registro.

Non bisogna, però, farsi ingannare dal fatto che la prima posizione, occupata da REG,[REG+DISP], implichi un maggior numero di caricamenti. In realtà in questa tipologia di argomenti ricade l’uso della famigerata istruzione LEA, che serve a caricare in un registro un indirizzo di memoria.

Poiché l’ABI x64 è pesantemente basata sull’uso dei registri come parametri delle funzioni da richiamare, si piega il perché dell’aumento di REG,[REG+DISP] rispetto a x86, come pure la completa scomparsa del singolo argomento dotato di valore immediato (IMM, usato per il push di valori immediati sullo stack in x86).

Un altro dato interessante che salta subito all’occhio è il massiccio uso dell’indirizzamento della memoria con la modalità più complessa, cioè [REG+REG*SC+DISP], che è presente in tutte le salse (contribuisce, anche qui, la diversa ABI): dall’uso coi registri general purpose, a quelli dell’unità SIMD SSE.

Infatti si nota immediatamente come le SSE facciano la parte del leone, con numeri abbastanza consistenti, se paragonati all’uso dell’FPU per il codice x86. Ovviamente le istruzioni più frequenti sono quelle che fanno esclusivamente uso di registri SSE (SSE,SSE).

Altre rilevanti differenze con x86 si notano nell’assenza dell’accesso diretto alla memoria (etichettato con [DISP]), come pure la mancanza di utilizzo di registri “alti” (AH, BH, ecc.), chiaro segno di un minor ricorso alle caratteristiche “legacy“.

Saltano fuori, infine, istruzioni con tre operandi (REG,REG,IMM, utilizzato dalla relativa istruzione IMUL), e altre che servono a copiare il valore di un registro general purpose in uno SSE (SSE,REG). Si tratta di istruzioni rare, ma che sono riuscite a rientrare nelle prime 20 posizioni di quelle più frequenti.

Con ciò si conclude quest’analisi. Nel prossimo articolo della serie, come già anticipato, punteremo lo sguardo sulla frequenza delle istruzioni / mnemonici.

8 Commenti »

I commenti inseriti dai lettori di AppuntiDigitali non sono oggetto di moderazione preventiva, ma solo di eventuale filtro antispam. Qualora si ravvisi un contenuto non consono (offensivo o diffamatorio) si prega di contattare l'amministrazione di Appunti Digitali all'indirizzo info@appuntidigitali.it, specificando quale sia il commento in oggetto.

  • # 1
    TheFoggy
     scrive: 

    Come sempre ottimo articolo, Cesare! Adoro questi articoli prettamente tecnici e molto più “pratici” di molti altri.

    Andando, ora, un filino OT chiedo: cosa sta succedendo ad AppuntiDigitali? Ultimamente vengono postati articoli con frequenza decisamente calata (prima era uno al giorno circa..ora siamo a due alla settimana!) e, coincidenza o no, mi pare sia successo tutto da quando i cugini/fratelli di HWU vi han relegato al fondo della loro home page..come se ora aveste perso lettori e quindi..via di tagli. Mi spiace tanto, perché spererei di non perdere l’opportunità di leggere articoli come questo (questa serie, e le precedenti curate da Cesare), o quelli di Simone (di cui ho apprezzato particolarmente i discorsi sui motori a combustione interna e i sistemi propulsivi aeronautici), mentre pare persa l’occasione di leggere ulteriori articoli di Yossarian. È un vero peccato, perché sembravate partici benissimo…e invece sembra che ora vi stiate affossando con le vostre stesse mani (o con quelle del grande gruppo editoriale “sopra” di voi…).

    Attendiamo che AD torni quello di un tempo. Credo di non essere l’unico a sperarlo!

  • # 2
    Cesare Di Mauro (Autore del post)
     scrive: 

    Grazie, ma ti assicuro che è un piacere scriverli. :) Tempo permettendo.

    Con ciò rispondo in parte alle tue domande, ma a titolo puramente personale: per me (ma credo di non essere il solo) è proprio una questione di tempo. Scrivere articoli come questo mi richiede diverse ore, e negli ultimi mesi ho avuto parecchia difficoltà a trovare non solo quello, ma anche la giusta concentrazione, avendo diverse cose abbastanza importanti a cui pensare.

    In tutto ciò non ha colpa la nuova impostazione grafica del sito principale di Hardware Upgrade, perché noi scriviamo indipendentemente dal layout. Se hai notato ciò, ti assicuro essere stato un fattore puramente contingente.
    I lettori sono certamente importanti per il sito, altrimenti sarebbe già stato chiuso da un pezzo. Un sito può essere bello quanto vuoi, ma se non riesce ad autosostenersi è destinato all’oblio. Non so esattamente come sia la nostra situazione da questo punto di vista, ma… siamo ancora aperti e, dunque, mi lascia sperare per il futuro.
    Ti posso dire in ogni caso, e in tutta onestà, che questo sito non porta ricchezza né ad HW né a noi: se siamo qui è per pura passione.

    Certamente Appunti Digitali ha bisogno di nuovi redattori per coprire, si spera di nuovo giornalmente, gli spazi che al momento sono rimasti vuoti. Se non leggi più pezzi di Yossarian, Pleg, Eleonora, è perché purtroppo non hanno più tempo per scrivere (magari capiterà qualche volta; dipende tutto da loro), e trovare delle figure al loro livello è veramente difficile. Almeno per noi, che abbiamo l’obiettivo di mantenere alta la qualità degli articoli, cosa che, spero sia anche l’opinione di chi ci legge, bene o male ci ha contraddistinto in tutti questi anni.

    Non è nostra intenzione tornare a scrivere articoli tirati sù in mezzoretta o poco più, come capitava agli albori. Per questo abbiamo la necessità sia di professionisti di spessore che, lo riporto nuovamente, tempo da dedicare allo studio e alla stesura dei pezzi. E magari ripensare un po’ AD in qualche modo per cercare di conciliare le esigenze personali con quelle della sopravvivenza del sito.

    In tutta onestà io non posso più continuare a scrivere articoli chilometrici. Non ce la faccio più. Ogni tanto qualcuno salta fuori, perché comincio a scrivere e le mani vanno avanti da sole.
    Credo che il modello migliore da seguire sia quello delle serie di articoli, con le informazioni distribuite su diversi pezzi, dove però ogni pezzo non sia troppo corto per non lasciare il lettore con l’amaro in bocca perché ha finito troppo presto di leggere. Una serie non è necessariamente un male o un spezzatino: può anche essere l’occasione per soffermarsi maggiormente su alcuni aspetti che altrimenti verrebbero accennati o nemmeno riportati.
    L’importante è riuscire a trovare un giusto equilibrio fra la qualità dei contenuti e la soddisfazione dei lettori, lasciando al contempo un po’ di respiro ai redattori. Per questo il vostro feedback è e sarà sempre indispensabile per capire se la strada che seguiamo è giusta.

    Lato mio sto cercando di completare il prima possibile questa lunga serie. Cosa succederà dopo è ancora da definire, perché questo è per me un mese di enormi cambiamenti e scelte di vita radicali, per cui dovrò valutare molte cose. Spero di poter continuare a contribuire, perché sono particolarmente legato a questo progetto editoriale. Poi è da anni che vorrei scrivere una serie molto tecnica sull’Amiga, raccontando come ho sviluppato i miei giochi, scendendo anche molto a basso livello, e mi spiacerebbe non poterlo realizzare. Ma tutto dipenderà dal mio prossimo futuro…

  • # 3
    TheFoggy
     scrive: 

    Grazie per la risposta, innanzitutto! Sono felice di sapere che i “disservizi” (concedimi il termine! ;) ) sia imputabile solo alla mancanza di tempo, dato anche dal fatto che non è un’attività remunerativa, che ovviamente hanno la precedenza! Capisco anche la difficoltà nel trovare personaggi di spicco che siano anche buoni comunicatori..ma lasciami sperare che la situazione migliori! :)
    Il discorso degli articoli a puntate, lo apprezzo molto (specifico, perchè dal tuo ” Una serie non è necessariamente un male o un spezzatino” sembra che qualcuno se ne sia lamentato), perchè permette di avere articoli approfonditi, ma senza dover perdere 5 ore di fila per leggerlo! Magari con un riavvio del pc per qualche motivo che ti fa perdere “il segno”.. Inoltre è più comodo per porre eventuali domande e seguire discorsi! Se fosse un articolo da 100 pagine, le domande apparterrebbero alle parti più disparate..trova poi la risposta che cercavi/aspettavi!!
    Detto questo, vi ( ok, mento..più che VI auguro, MI auguro! :P ) auguro di continuare come avete fatto fin’ora e, se possibile, di trovare personaggi degni di nota da inserire nello staff. Purtroppo non rientro in questa categoria, o mi sarei già candidato in qualche modo! ;)
    In ogni caso, continuerò a seguirvi, perchè articoli tecnici a livello medio/alto in italiano non se ne trovano…e dopo una giornata passata al pc, sinceramente non ho le forze per leggere e capire articoli in inglese, letti per puro diletto.. :)

    Spero di vedere i tuoi articoli tecnici sull’amiga e sulle tecniche da te ideate per svilupparci giochi, molto presto!!
    Per ora, buone vacanze, Cesare, a te e a tutti i membri della redazione!! In bocca al lupo!

  • # 4
    banryu
     scrive: 

    Grande serie di articoli, Cesare!
    Molto interessante, anche se personalmente attendo più la serie sullo sviluppo di giochi per amiga, mi intriga parecchio…
    Nel frattempo, in bocca al lupo e passa delle buone vacanze!

  • # 5
    Antonio Barba
     scrive: 

    La serie è molto molto tecnica e interessante, conosco gente che con ricerche molto meno dettagliate di questa ci ha fatto una tesi di laurea :D

  • # 6
    Cesare Di Mauro (Autore del post)
     scrive: 

    ROFL :D

    Grazie a tutti. Il prossimo articolo è finalmente pronto, ma m’è scappata la mano (in realtà c’era anche parecchio da dire, anche perché l’argomento lo permette decisamente) ed è venuto fuori un po’ più lungo del solito, per cui lo troverete pubblicato la prossima settimana. :P

    Per la serie dedicata all’Amiga vedremo se sarà possibile lavorarci al rientro dalle ferie.

  • # 7
    Claudio La Rosa
     scrive: 

    Ciao,
    vado un attimo OT.

    Indipendentemente dal processore (in questi articoli si parla di x86), vorrei capire quali architetture prevedono l’uso di 4 operandi nelle loro istruzioni e quanto questo può essere realmente utile usarne 4.

  • # 8
    Cesare Di Mauro (Autore del post)
     scrive: 

    Ciao Claudio.
    Dipende esclusivamente dal tipo di operazioni eseguite. 4 operandi in istruzioni “general purpose” a memoria non ne ricordo.

    Mentre per le unità SIMD sarebbero utili per implementare le famose operazioni FMAC/FMA, ossia moltiplicazione di un operando con un altro, somma del risultato con un altro operando, e infine conservazione di quest’ultimo risultato in un altro registro. Sono pattern di istruzioni che si trovano nel calcolo matriciale o nel codice tipicamente DSP (ma in questo caso, essendo usate più che altro come istruzioni di “accumulo”, primo operando e destinazione in genere coincidono).

    Altre operazioni con 4 operandi sono quelle cosiddette di “blending”, che consentono di selezionare specifiche parti di un registro o di un altro, usando un terzo registro per selezionare quale delle due debba essere usato, e infine conservando il risultato in un quarto registro.

    Un’altra interessantissima operazione che richiede 4 operandi è quella che Intel ha introdotto con le AVX-512, che consente di applicare una funzione logica a 3 operandi generandone un quarto: https://github.com/HJLebbink/asm-dude/wiki/VPTERNLOGD_VPTERNLOGQ
    Utilissima per… implementare roba come il Blitter dell’Amiga, ma con prestazioni elevatissime (le AVX-512 lavorano con operandi a 512-bit). :D

    Comunque le istruzioni che prevedono 4 operandi nei processori Intel (alcuni RISC le implementano pure, come PowerPC/Altivec, RISC-V/Vector extension) non sono molte. Se sei interessato posso fornirti l’elenco; fammi sapere. ;)

Scrivi un commento!

Aggiungi il commento, oppure trackback dal tuo sito.

I commenti inseriti dai lettori di AppuntiDigitali non sono oggetto di moderazione preventiva, ma solo di eventuale filtro antispam. Qualora si ravvisi un contenuto non consono (offensivo o diffamatorio) si prega di contattare l'amministrazione di Appunti Digitali all'indirizzo info@appuntidigitali.it, specificando quale sia il commento in oggetto.