Jump to content
PLC Forum


comparare 2 numeri 16 bit su un micro 8 bit in asm


polmax
 Share

Recommended Posts

Buona sera a tutti,

Il primo problema è già descritto nel titolo.

Il secondo (che dovrebbe aiutarmi a risolvere il primo) è quello di risalire alla AN di microchip che descrive la soluzione

Grazie

Polmax

Link to comment
Share on other sites


Il problema principale è la notazione. 16 bit intero con o senza segno? Comparazione solo uguali o diversi o anche maggiore/minore?

E non ultimo, per quale processore? Se è un PIC, ti aiuto poco, non ho mai voluto/avuto modo di vederne l'assembler. Per 8051, Z80, TMS9900, 6502 e simili, meglio...

In generale, si fa una sottrazione tra i due valori e se ne vede il risultato. Se positivo, il primo era maggiore del secondo, se negativo, era minore. Se zero, erano uguali. Bisogna però stare attenti al segno, se c'è.

Link to comment
Share on other sites

purtroppo è un PIC!

Si, x comparazione intendo tutte le possibilità tra due variabili lunghe 16 bits frazionate in due da 8 bits (High e Low) e senza segno

Link to comment
Share on other sites

Come detto, non conosco l'oggetto e non so se esistono routine di libreria già pronte, ho trovato comunque una routine che esegue la sottrazione a 16 bit:

;*******************************************************************
; Double Precision Subtraction
;
; Subtraction : ACCb(16 bits) - ACCa(16 bits) -> ACCb(16 bits)
; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits )
; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits )
; (c) CALL D_sub
; (d) The result is in location ACCbLO & ACCbHI ( 16 bits )
;
; Performance :
; Program Memory : 4 (excluding call & return )
; Clock Cycles : 4 (excluding call & return )
; W Register : Used
; scratch RAM : 0
;*******************************************************************;
;
D_sub
 movfp ACCaLO,WREG
 subwf ACCbLO, F
 movfp ACCaHI,WREG
 subwfb ACCbHI, F
 return
;*******************************************************************;

Dopo questa, basta guardare il risultato (16 bit), e se i due byte sono 0, i valori erano uguali; se non sono 0, guarda il byte alto e se il suo bit alto (bit 7) è a 1, il risultato è negativo, quindi il secondo valore era maggiore del primo; se è a 0, il primo era maggiore del secondo.

Gli esperti di PIC potranno darti routine più complete.

Link to comment
Share on other sites

21 minuti fa, Ctec ha scritto:

Come detto, non conosco l'oggetto e non so se esistono routine di libreria già pronte, ho trovato comunque una routine che esegue la sottrazione a 16 bit:

;*******************************************************************
; Double Precision Subtraction
;
; Subtraction : ACCb(16 bits) - ACCa(16 bits) -> ACCb(16 bits)
; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits )
; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits )
; (c) CALL D_sub
; (d) The result is in location ACCbLO & ACCbHI ( 16 bits )
;
; Performance :
; Program Memory : 4 (excluding call & return )
; Clock Cycles : 4 (excluding call & return )
; W Register : Used
; scratch RAM : 0
;*******************************************************************;
;
D_sub
 movfp ACCaLO,WREG
 subwf ACCbLO, F
 movfp ACCaHI,WREG
 subwfb ACCbHI, F
 return
;*******************************************************************;

Dopo questa, basta guardare il risultato (16 bit), e se i due byte sono 0, i valori erano uguali; se non sono 0, guarda il byte alto e se il suo bit alto (bit 7) è a 1, il risultato è negativo, quindi il secondo valore era maggiore del primo; se è a 0, il primo era maggiore del secondo.

Gli esperti di PIC potranno darti routine più complete.

Grazie Ctec,

Proverò questa strada

Link to comment
Share on other sites

Bisognerebbe specificare anche quale PIC. Le serie midrange 12..16 ad esempio non dispongono di somme e sottrazioni con riporto, e quella sottrazione non può essere eseguita in modo così semplice (è necessario propagare il riporto/prestito "a mano" sul byte alto dopo la gestione del byte basso).

Link to comment
Share on other sites

come ho indicato nel titolo, si tratta di un micro 8 bit (midrange) e nello specifico un PIC16f917.

2 ore fa, Claudio F ha scritto:

Bisognerebbe specificare anche quale PIC. Le serie midrange 12..16 ad esempio non dispongono di somme e sottrazioni con riporto, e quella sottrazione non può essere eseguita in modo così semplice (è necessario propagare il riporto/prestito "a mano" sul byte alto dopo la gestione del byte basso).

2 ore fa, Claudio F ha scritto:

Bisognerebbe specificare anche quale PIC. Le serie midrange 12..16 ad esempio non dispongono di somme e sottrazioni con riporto, e quella sottrazione non può essere eseguita in modo così semplice (è necessario propagare il riporto/prestito "a mano" sul byte alto dopo la gestione del byte basso).

Il 24/10/2022 alle 10:16 , Ctec ha scritto:

Come detto, non conosco l'oggetto e non so se esistono routine di libreria già pronte, ho trovato comunque una routine che esegue la sottrazione a 16 bit:

;*******************************************************************
; Double Precision Subtraction
;
; Subtraction : ACCb(16 bits) - ACCa(16 bits) -> ACCb(16 bits)
; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits )
; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits )
; (c) CALL D_sub
; (d) The result is in location ACCbLO & ACCbHI ( 16 bits )
;
; Performance :
; Program Memory : 4 (excluding call & return )
; Clock Cycles : 4 (excluding call & return )
; W Register : Used
; scratch RAM : 0
;*******************************************************************;
;
D_sub
 movfp ACCaLO,WREG
 subwf ACCbLO, F
 movfp ACCaHI,WREG
 subwfb ACCbHI, F
 return
;*******************************************************************;

Dopo questa, basta guardare il risultato (16 bit), e se i due byte sono 0, i valori erano uguali; se non sono 0, guarda il byte alto e se il suo bit alto (bit 7) è a 1, il risultato è negativo, quindi il secondo valore era maggiore del primo; se è a 0, il primo era maggiore del secondo.

Gli esperti di PIC potranno darti routine più complete.

Grazie Ctec,

Proverò questa strada

Link to comment
Share on other sites

Sono 14 anni che non uso un PIC (e non ne rimpiango affatto l'orrido assembly...)

 

Sulla falsa riga della subroutine postata, la versione che dovrebbe dare il corretto risultato numerico (ma NON il corretto settaggio finale dei flag) è la seguente:

 

D_sub
    movf    ACCaLO,W
    subwf   ACCbLO,F   ; ACCbLO = ACCbLO - ACCaLO
    btfss   STATUS,C   ; Se non prestito skip
    decf    ACCbHI,F   ; altrimenti propaga prestito
    movwf   ACCaHI,W
    subwf   ACCbHI,F   ; ACCbHI = ACCbHI - ACCaHI
    return

 

Determinare se il risultato è zero (e quindi i due numeri sono uguali) è semplice, basta fare l'or dei byte alto e basso:

 

    movf    ACCbLO,W
    iorwf   ACCbHI,W

 

Se invece ci serve anche il flag C per determinare le altre condizioni, minore, maggiore ecc, allora bisogna salvarsi l'eventuale prestito intermedio per regolare il flag C alla fine (in accordo con le specifiche dei PIC: 0=prestito 1=nessun prestito):

 

D_sub
    bsf     temp,0     ; Imposta nessun prestito iniziale
    movf    ACCaLO,W
    subwf   ACCbLO,F   ; ACCbLO = ACCbLO - ACCaLO
    btfsc   STATUS,C   ; Se prestito skip
    goto    J001       ; altrimenti salta
    movlw   1
    subwf   ACCbHI,F   ; Propaga eventuale prestito
    btfss   STATUS,C   ; Se non nuovo prestito skip
    bcf     temp,0     ; altrimenti salvalo
J001
    movwf   ACCaHI,W
    subwf   ACCbHI,F   ; ACCbHI = ACCbHI - ACCaHI
    btfss   temp,0     ; Se no precedente prestito skip
    bcf     STATUS,C   ; altrimenti resetta flag C
    return

 

Spero sia giusto, e sono anni che mi domando se non ci sia un modo più "umano". Perfino su un vecchio Z80 del 76 è infinitamente più semplice (e a parità di clock pure più veloce):

 

    LD   HL,(ACCb)
    LD   DE,(ACCa)
    AND  A
    SBC  HL,DE      ; HL = ACCb - ACCa

 

Link to comment
Share on other sites

Ma ti converrebbe usare il "C", anche quello con il compilatore poco ottimizzato in versione gratuita?

Quando usavo i PIC ricorrevo all'ASM solo per quelle parti in cui era indispensabile per minimizzare il codice.

Link to comment
Share on other sites

Grazie Claudio: proverò la tua routine e ti farò sapere al più presto.

Per quanto riguarda il consiglio di Orsini manifestatomi più volte in precedenza posso affermare che sono d'accordo!... E' una mia scelta dettata dallo scarso tempo a disposizione che mi induce in primis ad imparare un linguaggio (ad un livello sufficiente) prima di passare allo studio del successivo.

Voglio prima capire cosa "nasconde" un'istruzione in C prima di usarla.

polmax

Link to comment
Share on other sites

45 minuti fa, polmax ha scritto:

Voglio prima capire cosa "nasconde" un'istruzione in C prima di usarla.

 

Se vuoi ci deve essere l'opzione del compilatore che ti da per ogni linea l'esploso dello ASM.

Io l'ho usata nelle occasione in cui volevo ridurre al massimi il tempo di esecuzione. Se e quando un gruppo di istruzioni asm poteva essere ridotto ed ottimizato per velocità e/o per occupazione di memoria, al posto della linea di "C", usando le direttive "asm" ... "endasm" riscrivevo la linea un asm minimizzato.

A esempio in questo caso scrivi l'istruzione " if (Ia > Ib)......", compili e ti studi come è stata risolta la comparazione a livello di ASM.

Link to comment
Share on other sites

4 ore fa, polmax ha scritto:

come inizire ad imparare il C?

 

Molto dipende dal tuo retroterra culturale.

Come esempio ti descrivo il mio percorso. e quello di mia figlia.

Quando ho iniziato a studiare il "C", avevo alle spalle la cultura di qualche esame universitario di informatica e la relativa preparazione. Inoltre già programmavo con PL, PLM-80/51 e Pascal, tutti linguaggi con architettura molto simile al C. Quindi non c'è stato alcun sforzo, solo qualche prova per verificare che il mio approccio non fosse completamente fuori luogo. Poi ogni volta che mi imbattevo in un problema con differenze rispetto alle precedenti esperienze, andavo a ricercare l'argomento sul Ritchie & Kernighan, che è un po il vangelo del linguaggio "C".

Quando mia figlia, fine anni '80, allieva del politecnico di Milano, dovetta preparare un esame proprio sul linguaggio "C", gli installai un compilatore "C" a riga di comando sul PC; lei seguendo, capitolo dopo capitolo, il Ritchie & Kernighan, verificando i risultati con programmi di prova su PC imparò il linguaggio abbastanza velocemente.

Intendiamoci si può arrivare velocemente al padroneggiamento di circa lo 80% delle potenzialitò del linguaggio. Per apprendere l'altro 20% la funzione conoscenza-tempo diventa assintotica ed ad andamento esponenziale. Il tempo di apprendimento assomiglia all'adamento della tensione di carica del condensatore.🙂

 

Io ti consiglio di usare il commpilatore HiTe fornito free da Microchip nell'ambiente di MpLab. Se hai un sistemino di sviluppo della Microchip ti facilita di molto le cose.

Se leggi senza molto sforzo i testi in inglese usa i tutorial Microchip che ti insegnano ad usare il compilatore passo-passo.

 

 

Link to comment
Share on other sites

Il mio "retroterra" è assai limitato: "pic by esample" di Tanzilli (non so se lo conosci) e tante prove sul debugger del MPLAB osservando cosa succedeva nel file register.

Sarebbe per me interessante (e probabilmente mi faciliterebbe l'apprendimento) un confronto su programmini di base tra l'assembler ed il C.

Mi sa che dovrò procurarmi una copia di Ritchie & Kernighan

Grazie ancora

 

 

Link to comment
Share on other sites

13 ore fa, polmax ha scritto:

"pic by esample" di Tanzilli

 

risale ad oltre 20 anni fa ma è sempre un ottimo tutorial per muovere i primi passi nel mondo PIC.

13 ore fa, polmax ha scritto:

Mi sa che dovrò procurarmi una copia di Ritchie & Kernighan

 

E un testo fandamentale, una sorta di vangelo per il "C".

Link to comment
Share on other sites

C'è anche da considerare che sul micro non servirà "tutto" il C o tutto quello che si può fare col C, principalmente per la pochissima memoria RAM disponibile e l'assenza di un sistema operativo, per cui quello che si userà sarà un molto ridotto sottoinsieme: tipi di variabili, operazioni aritmetiche e logiche, le strutture decisionali if/switch, i cicli for/while, le funzioni come subroutine. Anche l'argomento puntatori credo sia inizialmente irrilevante, non si faranno  di certo allocazioni di memoria, liste concatenate ecc

Link to comment
Share on other sites

Io ho iniziato con i PIC 16c84 con il corso che fece elettronica in e il programmatore su porta parallela, anch'io io letto il pic by esemplari di Sergio Tanzilli.

Io mi trovo bene anche con il basic contenuto nel Pic IDE One shot, anche qui puoi andare a vedere cosa ha tradotto in asm con i riferimenti al sorgente.

Come dico sempre dipende cosa uno deve fare... 

 

Link to comment
Share on other sites

13 ore fa, Claudio F ha scritto:

C'è anche da considerare che sul micro non servirà "tutto" il C o tutto quello che si può fare col C,

 

Non è del tutto corretto, dipende dal micro che impieghi.

I compilatori dedicati ai microprocessori/microcontrollori hanno sempre la necessità di avere direttive, implicite o esplicite, per individuare la famiglia a cui sono rivolti.

I compilatori dedicati alle famiglie microchip possono compilare per i piccoli 8 bit con qualche kbyte di flash e poca RAM, sino ai 32 bit con flash e RAM pari a quelle dei PC di inizio secolo.

Quindi le limatazioni del compilatore non sono fisse, così come la larghezza delle parole.

Ma qui si aprirebbe un discorso che necessiterebbe non di poche righe, ma di aclune pagine.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...