Witam, po dłuższej przygodzie z Asemblerem postanowiłem zapoznać się z C dla procesorów AVR. Ku mojemu zdziwieniu prosty kod taki jak:
Zmieniany jest w taki kod:
Zupełnie nie rozumiem:
- do czego są użyte rejestry r0, r1 i dlaczego są odkładane na stosie?
- po co używana jest pamięć RAM (ST,LD) skoro mamy aż 32 rejestry i można by wartość zmiennej "a" trzymać w jednym z rejestrów?
- dlaczego obsługa przerwania nie jest na końcu kodu tylko później są jeszcze dwa rozkazy?
#include <avr/io.h>
#include <avr/interrupt.h>
int main(void)
{
// ustawienie trybu pracy licznika
TCCR0 = 0x04;
// wpisanie wartości początkowej
TCNT0 = 254;
// odblokowanie przerwania od licznika
TIMSK = 0x01;
// globalne odblokowanie przerwań
sei();
PORTB = 0x55;
for(;;){asm volatile("nop"::);}
}
SIGNAL (SIG_OVERFLOW0)
{
TCNT0 = 254;
static char a=0;
PORTB = a;
a++;
}
Zmieniany jest w taki kod:
+00000000: C012 RJMP PC+0x0013 Relative jump
+00000001: C021 RJMP PC+0x0022 Relative jump
+00000002: C020 RJMP PC+0x0021 Relative jump
+00000003: C01F RJMP PC+0x0020 Relative jump
+00000004: C01E RJMP PC+0x001F Relative jump
+00000005: C01D RJMP PC+0x001E Relative jump
+00000006: C01C RJMP PC+0x001D Relative jump
+00000007: C01B RJMP PC+0x001C Relative jump
+00000008: C01A RJMP PC+0x001B Relative jump
+00000009: C025 RJMP PC+0x0026 Relative jump
+0000000A: C018 RJMP PC+0x0019 Relative jump
+0000000B: C017 RJMP PC+0x0018 Relative jump
+0000000C: C016 RJMP PC+0x0017 Relative jump
+0000000D: C015 RJMP PC+0x0016 Relative jump
+0000000E: C014 RJMP PC+0x0015 Relative jump
+0000000F: C013 RJMP PC+0x0014 Relative jump
+00000010: C012 RJMP PC+0x0013 Relative jump
+00000011: C011 RJMP PC+0x0012 Relative jump
+00000012: C010 RJMP PC+0x0011 Relative jump
+00000013: 2411 CLR R1 Clear Register
+00000014: BE1F OUT 0x3F,R1 Out to I/O location
+00000015: E5CF LDI R28,0x5F Load immediate
+00000016: E0D4 LDI R29,0x04 Load immediate
+00000017: BFDE OUT 0x3E,R29 Out to I/O location
+00000018: BFCD OUT 0x3D,R28 Out to I/O location
+00000019: E010 LDI R17,0x00 Load immediate
+0000001A: E6A0 LDI R26,0x60 Load immediate
+0000001B: E0B0 LDI R27,0x00 Load immediate
+0000001C: C001 RJMP PC+0x0002 Relative jump
+0000001D: 921D ST X+,R1 Store indirect and postincrement
+0000001E: 36A1 CPI R26,0x61 Compare with immediate
+0000001F: 07B1 CPC R27,R17 Compare with carry
+00000020: F7E1 BRNE PC-0x03 Branch if not equal
+00000021: D002 RCALL PC+0x0003 Relative call subroutine
+00000022: C020 RJMP PC+0x0021 Relative jump
+00000023: CFDC RJMP PC-0x0023 Relative jump
@00000024: main
---- nuda.c ---------------------------------------------------------------------------------------
5: {
+00000024: E084 LDI R24,0x04 Load immediate
+00000025: BF83 OUT 0x33,R24 Out to I/O location
9: TCNT0 = 254;
+00000026: EF8E LDI R24,0xFE Load immediate
+00000027: BF82 OUT 0x32,R24 Out to I/O location
11: TIMSK = 0x01;
+00000028: E081 LDI R24,0x01 Load immediate
+00000029: BF89 OUT 0x39,R24 Out to I/O location
13: sei();
+0000002A: 9478 SEI Global Interrupt Enable
14: PORTB = 0x55;
+0000002B: E585 LDI R24,0x55 Load immediate
+0000002C: BB88 OUT 0x18,R24 Out to I/O location
16: for(;;){asm volatile("nop"::);}
+0000002D: 0000 NOP No operation
+0000002E: CFFE RJMP PC-0x0001 Relative jump
@0000002F: __vector_9
20: {
+0000002F: 921F PUSH R1 Push register on stack
+00000030: 920F PUSH R0 Push register on stack
+00000031: B60F IN R0,0x3F In from I/O location
+00000032: 920F PUSH R0 Push register on stack
+00000033: 2411 CLR R1 Clear Register
+00000034: 938F PUSH R24 Push register on stack
21: TCNT0 = 254;
+00000035: EF8E LDI R24,0xFE Load immediate
+00000036: BF82 OUT 0x32,R24 Out to I/O location
23: PORTB = a;
+00000037: 91800060 LDS R24,0x0060 Load direct from data space
+00000039: BB88 OUT 0x18,R24 Out to I/O location
24: a++;
+0000003A: 5F8F SUBI R24,0xFF Subtract immediate
+0000003B: 93800060 STS 0x0060,R24 Store direct to data space
25: }
+0000003D: 918F POP R24 Pop register from stack
+0000003E: 900F POP R0 Pop register from stack
+0000003F: BE0F OUT 0x3F,R0 Out to I/O location
+00000040: 900F POP R0 Pop register from stack
+00000041: 901F POP R1 Pop register from stack
+00000042: 9518 RETI Interrupt return
25: }
+00000043: 94F8 CLI Global Interrupt Disable
+00000044: CFFF RJMP PC-0x0000 Relative jump
Zupełnie nie rozumiem:
- do czego są użyte rejestry r0, r1 i dlaczego są odkładane na stosie?
- po co używana jest pamięć RAM (ST,LD) skoro mamy aż 32 rejestry i można by wartość zmiennej "a" trzymać w jednym z rejestrów?
- dlaczego obsługa przerwania nie jest na końcu kodu tylko później są jeszcze dwa rozkazy?
