C'den Meclise


16

Bir avr-8bit için aşağıdaki C koduna sahip olduğumuzu varsayalım:

int v1=1;
int v2=2;
v2=v2+v1;

Aşağıdaki sökülmeyi bekledim

ldi r18, 1;
ldi r19, 2;
add r19, r18;

ama koştuktan sonra:

avr-gcc -mmcu=atmega2560 Test.c -o Test.elf

ve

avr-objdump -S Test.elf > Test.lss

Aşağıdaki parçalara ayırdım

    ldi r24, 0x01   ; 1
    ldi r25, 0x00   ; 0
    std Y+2, r25    ; 0x02
    std Y+1, r24    ; 0x01
    ldi r24, 0x02   ; 2
    ldi r25, 0x00   ; 0
    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03
    ldd r18, Y+3    ; 0x03
    ldd r19, Y+4    ; 0x04
    ldd r24, Y+1    ; 0x01
    ldd r25, Y+2    ; 0x02
    add r24, r18
    adc r25, r19
    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03

Sökücünün sonucunu anlamama yardımcı olabilecek biri var mı?

Düzenleme: char kullanarak derleme haline:

ldi r24, 0x01
std Y+1, r24
ldi r24, 0x02
std Y+2, r24
ldd r25, Y+2
ldd r24, Y+1
add r24, r25
std Y+2, r24

STD talimatı ne zaman var?

Yanıtlar:


20

Kısa cevap: kayıtlarınız 8 bit ve değerleriniz 16 bit. Bu yüzden onları iki parça halinde ele alıyor.

Uzun cevap:

    ldi r24, 0x01   ; 1
    ldi r25, 0x00   ; 0

16 bit değeri 1'i 8 bitlik r24, r25 kayıtlarında saklayın.

    std Y+2, r25    ; 0x02
    std Y+1, r24    ; 0x01

Y + 1, Y + 2 yığın yerlerinde saklayın.

    ldi r24, 0x02   ; 2
    ldi r25, 0x00   ; 0

16 bitlik değer 2'yi 8 bitlik yazmaçlar r24, r25'te saklayın.

    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03

Y + 3, Y + 4 yığın yerlerinde saklayın.

    ldd r18, Y+3    ; 0x03
    ldd r19, Y+4    ; 0x04
    ldd r24, Y+1    ; 0x01
    ldd r25, Y+2    ; 0x02

Bunları yığından (r18, r19) ve (r24, r25) 'e geri kopyalayın

    add r24, r18
    adc r25, r19

İkinci eklemedeki taşıma da dahil olmak üzere (r24, r25) 'e (r18, r19) ekleyin

    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03

Yığının üzerinde saklayın.

Orijinal montajınızı almak için iki şeyi deneyin:

  • "char" değişkenlerini kullan
  • "-O2" derleyici seçeneğini kullan

Düzenleme : Derleyicinin değişkenleri kayıtlarda tutmak yerine yığına depolamasının nedeni, varsayılan "otomatik" depolama türüyle depolanmasıdır. Bu may kayıtları içine onları optimize ancak bu onları beyan bile "kayıt" depolama sınıfı, olmak zorunda değildir.

Bu dilin katı bir gereksinimi olmasa da normal derleyici davranışıdır. Bir noktada v1 adresini alırsak o zaman gerekir bir saklama yeri atanabilir ve oraya kaydedilmiş zaman "v1" değeri değişir. Bu nedenle, v1'in bir kayıt defterinde veya yığınta saklanıp saklanmayacağına ilişkin defter tutmayı kaydetmek için, yığın üzerinde tutar ve her bir kod satırını ayrı ayrı ele alır.


Teşekkür ederim! Şimdi daha açık! Lütfen düzenlemede soruyu bul.
DarkCoffee

1
Düzenlememe bakın. -O2'yi de deneyin. Belki -O3, bu kırık kod üretebilir rağmen.
pjc50

3
Birlikte çalıştığım gömülü kodların çoğu, boyutlarına özgü ek işaretler, örneğin işaretsiz girişler için "uint8, uint16, uint32" gibi tanımlar. Bu şekilde her zaman tam olarak hangi değişkenle uğraştığınızı bilirsiniz. Özellikle küçük gömülü, imzalı, kayan, tanımsız boyut / imzalı "int", CPU döngülerine en iyi şekilde mal olacak ve en kötü durumda ciddi hatalara neden olacaktır.
John U

Gerçek derleyiciler 10-15 yıl önce böyle davranmayı bıraktı. Kayıt tahsisi problemi çoğunlukla çözülür ve derleyiciler iyi durumdadır. Bir değişkenin yığın üzerinde ne zaman olması gerektiğini ve bir kayıtta ne zaman olabileceğini, onu taşımak için çaba harcamaya değer olup olmadığını ve ne zaman yapılacağını tam olarak bilirler. Defter tutma derleme zamanında yapılır ve derleyicilerin kendilerinin gigabayt belleği vardır. Büyük istisna, bariz nedenlerle hata ayıklama modudur, ancak daha sonra her şey yığın üzerindedir.
MSalters

@ pjc50 -O3bozuk kod üretebilir mi? [alıntı gerekli] (ve hayır, Tanımlanmamış Davranışı
başlatan

4

Bazı örnek kod bulduğumda, yorumumu cevaplayacağım - diğerleri sorunu zaten açıkladı.

Birlikte çalıştığım gömülü kodların çoğu, boyutlarına özgü ek işaretler, örneğin işaretsiz girişler için "uint8, uint16, uint32" gibi tanımlar. Bu şekilde her zaman tam olarak hangi değişkenle uğraştığınızı bilirsiniz. Özellikle küçük gömülü, imzalı, kayan, tanımsız boyut / imzalı "int", CPU döngülerine en iyi şekilde mal olacak ve en kötü durumda ciddi hatalara neden olacaktır.

İşte mevcut # tanımlarımız:

/*
 * Example - the basic data types from our embedded code
 */
typedef unsigned char       uint8;  /*  8 bits */
typedef unsigned short int  uint16; /* 16 bits */
typedef unsigned long int   uint32; /* 32 bits */

typedef char                int8;   /*  8 bits */
typedef short int           int16;  /* 16 bits */
typedef int                 int32;  /* 32 bits */

typedef volatile int8       vint8;  /*  8 bits */
typedef volatile int16      vint16; /* 16 bits */
typedef volatile int32      vint32; /* 32 bits */

typedef volatile uint8      vuint8;  /*  8 bits */
typedef volatile uint16     vuint16; /* 16 bits */
typedef volatile uint32     vuint32; /* 32 bits */

3
İyi bir fikir; uint8_t ve arkadaşları artık standardın bir parçası: stackoverflow.com/questions/16937459/…
pjc50

Ne kadar kullanışlı! C89 olan bir projeye sahip olanları miras aldık, bu yüzden resmi bir versiyonun olduğunu bilmek güzel.
John U

2

C kodunuz 16 bit tamsayı değişkenleri (int) kullanır. Derleyici fikrinizi okuyamaz, bu nedenle kaynak dosyada tam olarak ne olduğunu derler. Yani, 8 bit değişken istiyorsanız, ilgili türü kullanmanız gerekir.

Sonuç olarak, değerleri bellekte depolamaya devam edersiniz (daha basit olmasına rağmen). Ben C çok iyi değilim, ama IMHO, bazı değişkenler RAM yerine kayıtlarda olmasını istiyorsanız, bazı kayıt için değişken atamak için bazı seçenekler vardır. Gibi bir şey:

register unsigned char VARNAME asm("r3");

Bu tür numaralar için tüm kayıtların bulunmadığını unutmayın.

Sonuç olarak? Programlarınızı derlemeye yazın. Okumak / desteklemek her zaman daha küçük, daha hızlı ve kolay olacaktır.


Montajı okumak C'den daha mı kolay?
dext0rb

@ dext0rb - Evet. Tabii ki ikisini de yeterince tanıyorsanız. Sadece C'yi biliyorsanız, montaj ve diğer dilleri okumak zor olacaktır.
johnfound

Son noktaya katılmıyorum, montajcıda yazılmış programların okunması çok daha zor. Sadece yukarıda verilen kaynak kodunu karşılaştırın. C kodu, niyetinin yanı sıra çok daha açık ve kısa. Bu fark sadece yapılar kullanıldıkça büyür.
soandos

@soandos - C kodu daha kısa, evet. Daha net? Emin değilim. Öyle olsaydı, yukarıdaki sorunun hiç sorulması gerekmeyecekti. Aslında "kısalık" fiyatı ayrıntıların "bulanıklık" dır.
johnfound

Tabii ki, "C'de o kadar iyi değilim" diyen adam saf toplantının erdemlerini ilan edecek. : D
dext0rb
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.