Domanda:
Come posso impostare il codice della condizione in linguaggio assembly?
user5140
2012-03-29 18:01:17 UTC
view on stackexchange narkive permalink

Voglio testare il segno della variabile. In altre parole, voglio sapere se una variabile è positiva o negativa. Come posso scrivere seguendo le condizioni if-then-else in linguaggio assembly?

  if X > 0 goto A else goto B  

Sto usando PİC16f87x

Per fare in modo che la mia domanda sia più generale, se lo sai puoi dare risposta alle domande seguenti?

i.)

  if X > Y goto A else goto B  

ii.)

  if X > = Y goto A else goto B  

iii.)

  if X! = Y goto A else goto B  
Ricordo il codice assembler z80, ma si ottiene il confronto con la sottrazione e il controllo del carry e dello zero bit
Cinque risposte:
stevenvh
2012-03-29 19:14:47 UTC
view on stackexchange narkive permalink

Non conosco il microcontrollore PIC, quindi darò una risposta più generale. (modifica: risposta specifica per PIC aggiunta in fondo a questo post)

Soprattutto i microcontrollori più piccoli, come 8 bit e i loro derivati, sono limitati in ciò che possono fare in un singola istruzione. Un'istruzione può contenere l'indirizzo di destinazione per un salto, ma non due, quindi then-else è fuori. Hai solo la parte if-then , ma è sufficiente. Esistono due approcci. Alcuni controller ti consentono di passare a un determinato indirizzo se una condizione è soddisfatta, altri ti consentono solo di saltare l'istruzione successiva. Nel primo caso il tuo codice apparirà come segue:

  if-test-successs goto test-successtest-failed prima istruzione di `else` block ... goto continuetest-success prima istruzione di` then` blocca ... continua la prima istruzione dopo if-then-else  

Se puoi solo saltare l'istruzione successiva, scrivi qualcosa come

  if-test-successs salta la prossima istruzione goto test-failedtest-success prima istruzione del blocco `then` ... goto continuetest-fallita prima istruzione del blocco` else` ... continua prima istruzione dopo if-then-else  

Anche il test stesso ha possibilità limitate. Come se non potessi passare due numeri per confrontarli. Quello che devi fare è caricare l'accumulatore con il primo numero e nell'istruzione successiva sottrarre il secondo numero. Ciò farà sì che i codici di condizione come lo zero e i flag di trasporto vengano impostati / cancellati. Le istruzioni condizionali testeranno questi flag. Quindi, se vuoi scrivere if A = B then do-equal else do-not-equal questo diventerebbe

  carica accumulatore con A sottrai B dall'accumulatore se zero -flag set goto do-equaldo-not-equal prima istruzione del blocco `else` ...
goto continuedo-equal prima istruzione di `then` block ... continua prima istruzione dopo if-then-else  

Importante: il manuale del set di istruzioni ti dirà quali codici condizione saranno influenzati una data istruzione. Ad esempio, nella Z80 l'istruzione ld (per "load accumulator") non cambierà alcun flag. Quindi qui caricare l'accumulatore non è sufficiente per determinare se i dati sono zero.


modifica
OK, quindi ho fatto qualche ricerca e ho trovato quanto segue:
Il PIC ha solo 2 istruzioni di salto condizionale, BTFSS e BTFSC .

BTFSS : Bit Test F, Salta se impostato
Sintassi: BTFSS f, b
dove f è un registro [0..127]
e b è il bit in quel registro da testare [0..7]
Descrizione: Se il bit nel registro è 0 , viene eseguita l'istruzione successiva. Se il bit è 1 , l'istruzione successiva viene scartata e viene invece eseguito un NOP .

BTFSC : Bit Test F, Salta se Cancella
Sintassi: BTFSC f, b
dove f è un registro [0..127]
e b è il bit in quel registro da testare [0..7]
Descrizione: Se il bit nel registro è 1 , viene eseguita l'istruzione successiva. Se il bit è 0 , l'istruzione successiva viene scartata e al suo posto viene eseguito un NOP .

Rok Jarc
2012-03-29 18:23:36 UTC
view on stackexchange narkive permalink

Per ora risponderò solo alla prima parte della domanda.

Non menzioni il tipo di X - supponiamo che sia segno con segno. Il carattere con segno ha b.7 == 1 se negativo , quindi dobbiamo solo controllare lo stato di quel bit.

  // controllando se il bit 7 di X è azzerato (X.7 == 0) BTFSC X, 7 // se X.7 == 0 (X è positivo) salteremo l'istruzione successiva GOTO BGOTO A // controllando se il bit 7 di X è impostato (X.7 == 1) BTFSS X, 7 // se X.7 == 1 (X è negativo) salteremo la prossima istruzione GOTO AGOTO B  

Ecco un link a una bella guida: A Guide to Common PIC Assembly Programming Constructs

L'esempio sopra può essere trovato a pagina 7.

Cerca di capire da solo il resto delle risposte. Suggerimento: il commento di clabacchio è molto utile.

È lo stesso di: Jason Thweatt. "A Guide to Common PIC Assembly Programming Constructs". http://www.ucpic.byethost7.com/Downloads/ApuntesAssembler/Apunte2.pdf?
sì! grazie per l'avviso, non ho notato che il vecchio collegamento non è attivo. modificherà.
Rocketmagnet
2012-03-29 19:27:42 UTC
view on stackexchange narkive permalink

Per verificare se un numero intero è negativo, è necessario verificare solo il bit superiore. Se il bit superiore è 1, allora è negativo.

Ora, per un intero a 8 bit su un clabacchio a 8 bit menzionato, puoi usare una sottrazione per fare il test. Tuttavia, come regola generale, questo non è ottimale:

  1. I PIC hanno le utili istruzioni btfsc e btfss, che puoi usare per testare direttamente il bit superiore, come menzionato da rokjarc. Questo può anche essere usato per testare interi a 16 e 32 bit (e persino float!)

Questo è degno di nota, anche in C, perché ho visto i compilatori C di Microchip produrre codice stupido. Quando si verifica se un numero intero a 16 bit è maggiore di zero, produrranno letteralmente l'assembly per sottrarre il numero intero da zero e controlleranno i flag, invece di usare semplicemente btfss.

Quindi, ogni volta che io ' m scrivendo PIC C, controllo sempre l'output dell'assembly per vedere se sembra sensato. Quindi, di solito, scrivi macro per eseguire le operazioni. (A proposito, non ho effettivamente controllato queste macro, sono appena fuori dalla mia testa).

  #define IF_NEGATIVE_16_BIT (x) if (* ((int8 *) (( &x) +1)) & 0x80) #define IF_NEGATIVE_32_BIT (x) if (* ((int8 *) ((&x) +3)) & 0x80)  
  1. Altri microcontrollori avere l'istruzione AND. Solo AND il primo byte dell'intero con 0x80. Se viene impostato il flag zero, il numero intero non era negativo.
Olin Lathrop
2012-03-29 19:52:33 UTC
view on stackexchange narkive permalink

Per fare confronti tra interi e quasi tutto il resto in linguaggio assembly, devi capire come sono rappresentati i numeri.

La maggior parte delle variabili in un piccolo sistema embedded sono senza segno, o almeno dovrebbero esserlo. I programmatori di linguaggio di alto livello che sono abituati a sistemi più grandi tendono a non pensarci e usano variabili con segno quando è necessario solo senza segno. Unsigned è generalmente più facile da lavorare a basso livello.

Il tuo codice è per un PIC 16, quindi presumo che tu stia usando l'assembler MPASM. Ho un sacco di macro e altre funzionalità per aiutare con cose come il confronto della grandezza nel mio file di inclusione comune STD.INS.ASPIC, che fa parte del mio ambiente di sviluppo PIC. In particolare, le macro SKIP_WLE (salta se W era minore o uguale a) e SKIP_WGT (salta se W era maggiore di) servono per confrontare numeri senza segno.

Il PIC ha un bit di stato di riporto, chiamato C, che è l'uscita di riporto dell'ALU. Questo bit può essere testato dopo una somma o una sottrazione per vedere se è stato eseguito il bit alto dell'ALU. Il modo in cui le sottrazioni funzionano con i numeri in complemento a due, il bit C diventa un bit di non prestito dopo una sottrazione. Per rendere le cose più complicate, le istruzioni di sottrazione PIC sottraggono il registro W dall'operando, non il contrario. Devi fare un po 'di ginnastica mentale per tenere traccia del fatto che C non è un prestito e cosa è stato realmente sottratto da cosa e quindi cosa significa effettivamente un prestito. Ho fatto tutto questo una volta e ho incapsulato il risultato in queste due semplici macro, quindi non devo pensarci ogni volta e rischiare di rovinarlo. Su una PIC 16, SKIP_WLE si trasforma nella singola istruzione BTFSS STATUS, C e SKIP_WGT si trasforma in BTFSC STATUS, C.

Ecco come useresti queste macro nel codice:

 maxok equ 37; livello serbatoio OK massimo ... ;; Controllare il livello del serbatoio ed eseguire la routine di eccezione se lo è; troppo alto.; banksel tanklev; imposta banca per l'accesso a TANKLEV
movf tanklev, w; ottieni il livello pieno del serbatoio sublw maxok; confronta con il livello normale massimo skip_wle; il livello del serbatoio è entro l'intervallo? goto ohcrap; no ;; Il livello del serbatoio è entro i normali limiti operativi .; 

Ci sono molte altre cose utili in STD.INS.ASPIC. Ho anche un preprocessore che aggiunge molte funzioni utili al linguaggio MPASM. Ad esempio, può eseguire calcoli in virgola mobile in fase di compilazione, può manipolare stringhe reali per creare nomi di simboli, ha una capacità macro più flessibile e molto altro ancora.

davidcary
2012-10-12 20:28:05 UTC
view on stackexchange narkive permalink

16 bit confronta

  • X = XH: XL i byte Hi e Lo della variabile RAM X,
  • Y = YH: YL i byte Hi e Lo di la variabile RAM Y.

Tutti i valori sono senza segno.

 ; if (y < x) movfw XL subwf YL, w movfw XH skpc; c = 0 indica un prestito che dobbiamo propagare. incfsz XH, w; gestire correttamente XH = 0xff, a differenza di `` incf XH, w ''. subwf YH, w skpnc goto else; poi:; / * y è minore di x * / ... goto endifelse :; / * y NON è minore di x * / ... endif :; if (x < = y) movfw XL subwf YL, w movfw XH skpc; c = 0 indica un prestito che dobbiamo propagare. incfsz XH, w; gestire correttamente XH = 0xff, a differenza di `` incf XH, w ''. subwf YH, w skpc goto else; poi:; / * x è minore o uguale a y * / ... goto endifelse :; / * x NON è minore o uguale a y * / ... endif :; if (X == Y) movf XH, w xorwf YH, w skpz goto else movf XL, w xorwf YL skpz goto else; poi:; / * X è uguale a Y * / ... goto endifelse :; / * X non è la stessa cosa di Y * / ... endif:  

I programmatori del linguaggio Assembly in genere cambiano i tag "else:" e "endif:" in un'etichetta univoca (e si spera descrittiva) per ogni istruzione if. Forse qualcosa come "then_in_normal_range:", "else_outside_normal_range:" e "finish_range_handling:". (A differenza dei linguaggi di livello superiore come Pascal e BASIC dove usiamo le stesse parole "then" e "else" e " endif "per ogni istruzione if.).

Il codice sopra funziona solo quando sia X che Y sono nella RAM - Il PIC16f87x richiede istruzioni diverse per confrontare X con un valore costante.

Un modo per gestire i numeri con segno a 16 bit è capovolgere prima il bit alto

  movlw 0x80xorwf XH, wxorwf YH, w  

quindi utilizzare il sopra il codice di confronto. Successivamente, ripristina i valori originali capovolgendo di nuovo il bit alto

  movlw 0x80xorwf XH, wxorwf YH, w  

.

ps Spesso puoi ottenere una risposta molto più rapida alle domande sul PIC16f87x cercando nell'elenco PIC sito web http://piclist.com/ e il wiki di Microchip http://microchip.wikidot.com. Per i confronti con il linguaggio assembly, vedere la pagina "Confronti dei linguaggi di assemblaggio" sul wiki di Microchip e PIC Microcontroller Comparison Math Methods sul sito web PIClist (di cui quanto sopra è un piccolo estratto).



Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...