Assembly'de karşılaştırma ve eşitlik sorgulaması?

Başlatan Mucit23, 28 Mart 2014, 14:01:42

Mucit23

Assembly ile bir değişkendeki değeri sorgulatıp işlem yapmak istiyorum

örneğin if(a==5) {}
Bu komut değişkenin değerini sorgulatıyor. Aynısını assembly ile nasıl yaparım?

SpeedyX

Hatırladığım kadarıyla şöyle;

movlw 5
subwf a,w
btfss status,z
goto DEGISKEN_5_DEN_FARKLI
goto DEGISKEN_5_E_ESIT

Mucit23

Teşekkürler eşitlik sorgulamasını yaptım. Açıkçası bu asm yi sevmeye başladım.

ASM ile Büyüklük küçüklük sorgulamaları nasıl yapılır?

z

Çıkartma işlemi ardından Cary flağını test edeceksin.

A-B işleminde

A>B yada A=B ise Cary=1
A<B  Cary=0



Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Mucit23

Evet galiba her türlü çıkartma yapıp status registerinin flaglarını kontrol etmem gerekiyor.

RaMu

Evet birde Z(h)ero flag var :)

Hocam çıkarma yapmak istemezsen mantıksal işlemleride kullanabilirsin,
yine flaglara bakacaksın sonuçta,


andlw
andwf

iorlw
iorwf
xorwf
xorlw


işi uzatmak için böyle taklalar atılabilir
ör;
bilgi
ANDLW: Bir sayı ile W registerin içeriğine AND (VE) mantıksal işlemini uygula.

kullanımı:

ANDLW k

yukardaki kullanım sonucu pic şunu yapar;

W registerin içinde bulunan değer ile k sayısına and işlemini uygular ve çıkan sonucu W ye yazar.

işlem sonucunda 0 değeri elde edilirse, Status zero biti 1 yapılır.


Misal sayi == 0x0f mi?

movlw 0xf0     ;test için değerin tersini kullanıyoruz  (terslemek için 1 ile xor lama kullanılabilir)
andwf  sayi,w  ;sayi ile w yi andle sonucu w ye yaz (sayi içeriği değişmesin diye
                        ;eğer sonuç 0 ise status zero biti 1 olur,
;and işleminin sonucunun 0 olabilmesi için (sayi=)0x0f and 0xf0 olması gerekir
;0000 1111   sayı
;1111 0000   andlendiği değer
;_________  and işlemi
;0000 0000    sonuç
btfss    status,z ;status z biti 1 ise atla
goto     sayi_esit
goto     esit_degil


yada direk
xorlw
xorwf
kullanılarakta karşılaştırma yapılabilir.


;memo == 0xAA mı kontrolü (memo ==0xAA ise zero = 1 olur)

movlw  0xAA
xorwf    memo,w    ;memo ile w daki sayıyı xor la, sonucu w ya yaz
btfss     status,z     ;zero bayrağı 1 mi
goto   (aa değilse)  ;hayır
goto   (aa ise)         ;evet
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

kudretuzuner

Merhaba,
Projelerimin birinde PC'den giden datanın PIC tarafından algılanıp PC'den  klavye"1" basıldığı zaman XORWF ile karşılaştırıp
duruma göre yön veren bir kodu da ben paylaşayım dedim.Kolay gelsin.
;*************
MOVLW B'00110001'
XORWF RCREG
BTFSS STATUS,2
GOTO LED_GONDER
GOTO TESTCD
;*************
Amatör

Mucit23

Tekrardan bir konu açmaya gerek yok sanırım burdan devam edeyim.

Birkaç sorum olacak.

ASM ile kesme rutini yazdım. Kesme içerisinde display tarıyorum.
Yazdığım kodlar,
;***************************Kesme Rutini*******************************
INTERRUPT
  BANKSEL PORTD
  MOVLW H'00'        ;Eğer INT_SYC=0 ise
  SUBWF INT_SYC,W    ;INT_SYC Değişkeninden W yi çıkart
  BTFSS STATUS,Z     ;Z Flagı 1 ise işlem sonucu sıfırdır.
  GOTO BOLUM2        ;Z=0 ise INT_SYC sıfırdan farklıdır.
  BCF PORTD,2        ;3.Displayi Kapat
    MOVLW DIG0       ;1. Displayin Datasını W ye yükle
    MOVWF PORTC      ;W deki Değeri Displaye gönder
  BSF PORTD,0        ;Displayi Aç
  GOTO EXIT          ;Kesmeden Çık
BOLUM2
  MOVLW H'01'        ;Eğer INT_SYC=0 ise
  SUBWF INT_SYC,W    ;INT_SYC Değişkeninden W yi çıkart
  BTFSS STATUS,Z     ;Z Flagı 1 ise işlem sonucu sıfırdır.
  GOTO BOLUM3        ;Z=0 ise INT_SYC sıfırdan farklıdır.
  BCF PORTD,0        ;1.Displayi Kapat
    MOVLW DIG1       ;2. Displayin Datasını W ye yükle
    MOVWF PORTC      ;W deki Değeri Displaye gönder
  BSF PORTD,1        ;Displayi Aç
  GOTO EXIT          ;Kesmeden Çık
BOLUM3
  MOVLW H'02'        ;Eğer INT_SYC=0 ise
  SUBWF INT_SYC,W    ;INT_SYC Değişkeninden W yi çıkart
  BTFSS STATUS,Z     ;Z Flagı 1 ise işlem sonucu sıfırdır.
  GOTO EXIT          ;Z=0 ise INT_SYC sıfırdan farklıdır.
  BCF PORTD,1        ;2.Displayi Kapat
    MOVLW DIG2       ;3. Displayin Datasını W ye yükle
    MOVWF PORTC      ;W deki Değeri Displaye gönder
  BSF PORTD,2        ;Displayi Aç
  GOTO EXIT          ;Kesmeden Çık
  
EXIT                 
 INCF INT_SYC,F      ;INT_SYC 1 arttırılır   
 MOVLW H'03'         ;Eğer INT_SYC Değeri 3 ise 
 SUBWF INT_SYC,W     ;INT_SYC Değerini Sıfırla
 BTFSS STATUS,Z
 GOTO EXIT1
 MOVLW H'00'         ;INT_SYC Sıfırlandı
 MOVWF INT_SYC
EXIT1 
 BANKSEL TMR0        ;Timer0'ın bulunduğu bank'a geçiliyor. 
 MOVLW D'99'         ;Timer Preload değeri tekrar yükleniyor.
 MOVWF TMR0 
 BCF INTCON,TMR0IF
RETFIE


Burada displaylerin seğment bilgilerini DIG0, DIG1, DIG2 isimli değişkenler tutuyor. Bu değerleri kesme içerisinde ilk önce W ye yükleyip sonra port'a yazıyorum. Fakat debug esnasında örneğin W registerine DIG0 yüklenmesi gerekirken W de saçma sapan değerleri görüyorum. Dolayısıyla W deki Değer Port'a yazdığı için display'de anlamsız değerler çıkıyor. Bunun sebebi ne olabilir?

Diğer bir konu ise yine kesme ile ilgili. Kesme içerisinde W registerini kullandığım için ana programdan kesmeye gelindiğinde W 'de tutulan değer çöpe gitmiş oluyor. Bunun için Context Save işlemini yapmam gerekecek. Bu işlemin içeriği nedir? Sadece kesmeye gelindiğinde W deki değeri alıp, kesmeden çıkarkende tekrar W ye yüklemek yeterlimi?

Kabil ATICI

mplap temp dosysı içinde kesme örneği;

***** VARIABLE DEFINITIONS
w_temp        EQU     0x7E        ; variable used for context saving
status_temp   EQU     0x7F        ; variable used for context saving
;**********************************************************************
   ORG     0x000             ; processor reset vector
   goto    main              ; go to beginning of program
   
   ORG     0x004             ; interrupt vector location
   movwf   w_temp            ; save off current W register contents
   movf   STATUS,w          ; move status register into W register
   movwf   status_temp       ; save off contents of STATUS register

; isr code can go here or be located as a call subroutine elsewhere

   movf    status_temp,w     ; retrieve copy of STATUS register
   movwf   STATUS            ; restore pre-isr STATUS register contents
   swapf   w_temp,f
   swapf   w_temp,w          ; restore pre-isr W register contents
   retfie                    ; return from interrupt

evet, belirttiğin gibi yapılabilmekte.
ambar7

Mucit23

Hocam o kodda anlamadığım bir iki yer var.

Kesme vektörünün hemen altında  movwf w_temp komutu ile W deki değer w_temp'e alınıyor. Fakat kesmeden çıkarken neden swapf komutu kullanılmış anlamadım.

   swapf   w_temp,f
   swapf   w_temp,w          ; restore pre-isr W register contents

w_temp deki değerin direk W ye yüklenmesi gerekmezmiydi.?

Diğer bir yandan yaşadığım probleme hala yinede anlam veremiyorum. Ana program döngüsünde hiçbirşey yapmıyorum. Yani kesme rutini dışında W registeri kullanılmıyor. W 'ye kim bu değerleri yüklüyor anlamıyorum.

Kabil ATICI

programını bir incele,
dig0,...,dig3 değişken olarak belirtmişsin, ama programda sabit sayı gibi işlem yapmışsın gibi görünüyor...

ambar7

Mucit23

Doğruya MOVLW ile sabit sayı W'ye yazılıyordu. Benim MOVF kullanmam gerekiyordu. Sorun çözüldü. Context Save işlemlerinide yaparsam tamamdır.

RaMu

Alıntı yapılan: Mucit23 - 30 Mart 2014, 17:34:46
Hocam o kodda anlamadığım bir iki yer var.

Kesme vektörünün hemen altında  movwf w_temp komutu ile W deki değer w_temp'e alınıyor. Fakat kesmeden çıkarken neden swapf komutu kullanılmış anlamadım.

   swapf   w_temp,f
   swapf   w_temp,w          ; restore pre-isr W register contents

w_temp deki değerin direk W ye yüklenmesi gerekmezmiydi.?


Aslında bence girerkende swapla alınması iyi olur,
movf komutunun statusu etkileme ihtimali var
o yüzden swapf komutu kullanılıyor, şöyle örnekleyeyim;
misal w register ın içinde sıfır değeri vardı w_temp e alındı,
movf w_temp,w dersek w_temp içindeki sıfır değeri w register ına yazılır ve
yüklenen içerik sıfır olduğu için statusun zero bayrağı set 1 edilir,
eğer kesmeye gi,rerken status,z sıfır olsaydı ve w register ıda böyle sıfırla gelmiş olsaydı
çıkışta status zero bayrağı set edilmiş olacaktı buda hata olacaktı.


Pardon kesmeye girerken swapla almak ekstra bir fayda sağlamıyor,
bazı dökümanlarda karşılaşmıştım gibi hatırladım ama
herhalde burada faydası olmaz yine bakarım bir ara.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

Mucit23

Cevap için Teşekkürler,

Bir sorum daha olacak. Assembly ile Mod alma nasıl yaparım?

Amacım şudur. Örneğin 245 verisini hanelerine ayırmam gerekiyor. 2 sayısını bir değişkene, 4 sayısını bir değişkene 5 sayısınıda başka bir değişkene atmam gerekiyor. Bu işlem genelde 7 seğment display kullanırken lazım oluyor. PicBasic veya C gibi dillerde bölme ve mod alma işlemleriyle kolaylıkla yapıyoruz. Bizim kolaylıkla yaptığımız bu işi derleyici nasıl yapar?


Erol YILMAZ

245

Ydigit = 0;
x = 245;

ISLEM:
x sayısı ,
99 dan büyükse
   Ydigit+1
   x-100
   goto ISLEM: