x86アセンブラでプログラム
2024.02.13 18:09 | pmlink.png 固定リンク | folder.png その他・雑談
AVR マイコンのアーキテクチャと機械語
2024.02.13 17:41 | pmlink.png 固定リンク | folder.png その他・雑談
AVRシミュレータ
ブックマーク。
AVRシミュレータについてはこちら。

https://avr.jp/user/DT/PDF/AVR_Simulator.pdf
2024.02.13 17:39 | pmlink.png 固定リンク | folder.png その他・雑談
AVRstudioでアセンブラ
ちなみに短いプログラムを書いてみた。

start:
inc r16
rjmp start

アセンブルしたらこんな感じ。







;***** Created: 2011-02-09 12:03 ******* Source: ATmega328P.xml **********
;*************************************************************************
;* A P P L I C A T I O N N O T E F O R T H E A V R F A M I L Y
;*
;* Number : AVR000
;* File Name : "m328Pdef.inc"
;* Title : Register/Bit Definitions for the ATmega328P
;* Date : 2011-02-09
;* Version : 2.35
;* Support E-mail : avr@atmel.com
;* Target MCU : ATmega328P
;*
;* DESCRIPTION
;* When including this file in the assembly program file, all I/O register
;* names and I/O register bit names appearing in the data book can be used.
;* In addition, the six registers forming the three data pointers X, Y and
;* Z have been assigned names XL - ZH. Highest RAM address for Internal
;* SRAM is also defined
;*
;* The Register names are represented by their hexadecimal address.
;*
;* The Register Bit names are represented by their bit number (0-7).
;*
;* Please observe the difference in using the bit names with instructions
;* such as "sbr"/"cbr" (set/clear bit in register) and "sbrs"/"sbrc"
;* (skip if bit in register set/cleared). The following example illustrates
;* this:
;*
;* in r16,PORTB ;read PORTB latch
;* sbr r16,(1< ;* out PORTB,r16 ;output to PORTB
;*
;* in r16,TIFR ;read the Timer Interrupt Flag Register
;* sbrc r16,TOV0 ;test the overflow flag (use bit#)
;* rjmp TOV0_is_set ;jump if set
;* ... ;otherwise do something else
;*************************************************************************

#ifndef _M328PDEF_INC_
#define _M328PDEF_INC_


#pragma partinc 0

; ***** SPECIFY DEVICE ***************************************************
.device ATmega328P
#pragma AVRPART ADMIN PART_NAME ATmega328P
.equ SIGNATURE_000 = 0x1e
.equ SIGNATURE_001 = 0x95
.equ SIGNATURE_002 = 0x0f

#pragma AVRPART CORE CORE_VERSION V2E


; ***** I/O REGISTER DEFINITIONS *****************************************
; NOTE:
; Definitions marked "MEMORY MAPPED"are extended I/O ports
; and cannot be used with IN/OUT instructions
.equ UDR0 = 0xc6 ; MEMORY MAPPED
.equ UBRR0L = 0xc4 ; MEMORY MAPPED
.equ UBRR0H = 0xc5 ; MEMORY MAPPED
.equ UCSR0C = 0xc2 ; MEMORY MAPPED
.equ UCSR0B = 0xc1 ; MEMORY MAPPED
.equ UCSR0A = 0xc0 ; MEMORY MAPPED
.equ TWAMR = 0xbd ; MEMORY MAPPED
.equ TWCR = 0xbc ; MEMORY MAPPED
.equ TWDR = 0xbb ; MEMORY MAPPED
.equ TWAR = 0xba ; MEMORY MAPPED
.equ TWSR = 0xb9 ; MEMORY MAPPED
.equ TWBR = 0xb8 ; MEMORY MAPPED
.equ ASSR = 0xb6 ; MEMORY MAPPED
.equ OCR2B = 0xb4 ; MEMORY MAPPED
.equ OCR2A = 0xb3 ; MEMORY MAPPED
.equ TCNT2 = 0xb2 ; MEMORY MAPPED
.equ TCCR2B = 0xb1 ; MEMORY MAPPED
.equ TCCR2A = 0xb0 ; MEMORY MAPPED
.equ OCR1BL = 0x8a ; MEMORY MAPPED
.equ OCR1BH = 0x8b ; MEMORY MAPPED
.equ OCR1AL = 0x88 ; MEMORY MAPPED
.equ OCR1AH = 0x89 ; MEMORY MAPPED
.equ ICR1L = 0x86 ; MEMORY MAPPED
.equ ICR1H = 0x87 ; MEMORY MAPPED
.equ TCNT1L = 0x84 ; MEMORY MAPPED
.equ TCNT1H = 0x85 ; MEMORY MAPPED
.equ TCCR1C = 0x82 ; MEMORY MAPPED
.equ TCCR1B = 0x81 ; MEMORY MAPPED
.equ TCCR1A = 0x80 ; MEMORY MAPPED
.equ DIDR1 = 0x7f ; MEMORY MAPPED
.equ DIDR0 = 0x7e ; MEMORY MAPPED
.equ ADMUX = 0x7c ; MEMORY MAPPED
.equ ADCSRB = 0x7b ; MEMORY MAPPED
.equ ADCSRA = 0x7a ; MEMORY MAPPED
.equ ADCH = 0x79 ; MEMORY MAPPED
.equ ADCL = 0x78 ; MEMORY MAPPED
.equ TIMSK2 = 0x70 ; MEMORY MAPPED
.equ TIMSK1 = 0x6f ; MEMORY MAPPED
.equ TIMSK0 = 0x6e ; MEMORY MAPPED
.equ PCMSK1 = 0x6c ; MEMORY MAPPED
.equ PCMSK2 = 0x6d ; MEMORY MAPPED
.equ PCMSK0 = 0x6b ; MEMORY MAPPED
.equ EICRA = 0x69 ; MEMORY MAPPED
.equ PCICR = 0x68 ; MEMORY MAPPED
.equ OSCCAL = 0x66 ; MEMORY MAPPED
.equ PRR = 0x64 ; MEMORY MAPPED
.equ CLKPR = 0x61 ; MEMORY MAPPED
.equ WDTCSR = 0x60 ; MEMORY MAPPED
.equ SREG = 0x3f
.equ SPL = 0x3d
.equ SPH = 0x3e
.equ SPMCSR = 0x37
.equ MCUCR = 0x35
.equ MCUSR = 0x34
.equ SMCR = 0x33
.equ ACSR = 0x30
.equ SPDR = 0x2e
.equ SPSR = 0x2d
.equ SPCR = 0x2c
.equ GPIOR2 = 0x2b
.equ GPIOR1 = 0x2a
.equ OCR0B = 0x28
.equ OCR0A = 0x27
.equ TCNT0 = 0x26
.equ TCCR0B = 0x25
.equ TCCR0A = 0x24
.equ GTCCR = 0x23
.equ EEARH = 0x22
.equ EEARL = 0x21
.equ EEDR = 0x20
.equ EECR = 0x1f
.equ GPIOR0 = 0x1e
.equ EIMSK = 0x1d
.equ EIFR = 0x1c
.equ PCIFR = 0x1b
.equ TIFR2 = 0x17
.equ TIFR1 = 0x16
.equ TIFR0 = 0x15
.equ PORTD = 0x0b
.equ DDRD = 0x0a
.equ PIND = 0x09
.equ PORTC = 0x08
.equ DDRC = 0x07
.equ PINC = 0x06
.equ PORTB = 0x05
.equ DDRB = 0x04
.equ PINB = 0x03


; ***** BIT DEFINITIONS **************************************************

; ***** USART0 ***********************
; UDR0 - USART I/O Data Register
.equ UDR0_0 = 0 ; USART I/O Data Register bit 0
.equ UDR0_1 = 1 ; USART I/O Data Register bit 1
.equ UDR0_2 = 2 ; USART I/O Data Register bit 2
.equ UDR0_3 = 3 ; USART I/O Data Register bit 3
.equ UDR0_4 = 4 ; USART I/O Data Register bit 4
.equ UDR0_5 = 5 ; USART I/O Data Register bit 5
.equ UDR0_6 = 6 ; USART I/O Data Register bit 6
.equ UDR0_7 = 7 ; USART I/O Data Register bit 7

; UCSR0A - USART Control and Status Register A
.equ MPCM0 = 0 ; Multi-processor Communication Mode
.equ U2X0 = 1 ; Double the USART transmission speed
.equ UPE0 = 2 ; Parity Error
.equ DOR0 = 3 ; Data overRun
.equ FE0 = 4 ; Framing Error
.equ UDRE0 = 5 ; USART Data Register Empty
.equ TXC0 = 6 ; USART Transmitt Complete
.equ RXC0 = 7 ; USART Receive Complete

; UCSR0B - USART Control and Status Register B
.equ TXB80 = 0 ; Transmit Data Bit 8
.equ RXB80 = 1 ; Receive Data Bit 8
.equ UCSZ02 = 2 ; Character Size
.equ TXEN0 = 3 ; Transmitter Enable
.equ RXEN0 = 4 ; Receiver Enable
.equ UDRIE0 = 5 ; USART Data register Empty Interrupt Enable
.equ TXCIE0 = 6 ; TX Complete Interrupt Enable
.equ RXCIE0 = 7 ; RX Complete Interrupt Enable

; UCSR0C - USART Control and Status Register C
.equ UCPOL0 = 0 ; Clock Polarity
.equ UCSZ00 = 1 ; Character Size
.equ UCPHA0 = UCSZ00 ; For compatibility
.equ UCSZ01 = 2 ; Character Size
.equ UDORD0 = UCSZ01 ; For compatibility
.equ USBS0 = 3 ; Stop Bit Select
.equ UPM00 = 4 ; Parity Mode Bit 0
.equ UPM01 = 5 ; Parity Mode Bit 1
.equ UMSEL00 = 6 ; USART Mode Select
.equ UMSEL0 = UMSEL00 ; For compatibility
.equ UMSEL01 = 7 ; USART Mode Select
.equ UMSEL1 = UMSEL01 ; For compatibility

; UBRR0H - USART Baud Rate Register High Byte
.equ UBRR8 = 0 ; USART Baud Rate Register bit 8
.equ UBRR9 = 1 ; USART Baud Rate Register bit 9
.equ UBRR10 = 2 ; USART Baud Rate Register bit 10
.equ UBRR11 = 3 ; USART Baud Rate Register bit 11

; UBRR0L - USART Baud Rate Register Low Byte
.equ _UBRR0 = 0 ; USART Baud Rate Register bit 0
.equ _UBRR1 = 1 ; USART Baud Rate Register bit 1
.equ UBRR2 = 2 ; USART Baud Rate Register bit 2
.equ UBRR3 = 3 ; USART Baud Rate Register bit 3
.equ UBRR4 = 4 ; USART Baud Rate Register bit 4
.equ UBRR5 = 5 ; USART Baud Rate Register bit 5
.equ UBRR6 = 6 ; USART Baud Rate Register bit 6
.equ UBRR7 = 7 ; USART Baud Rate Register bit 7


; ***** TWI **************************
; TWAMR - TWI (Slave) Address Mask Register
.equ TWAM0 = 1 ;
.equ TWAMR0 = TWAM0 ; For compatibility
.equ TWAM1 = 2 ;
.equ TWAMR1 = TWAM1 ; For compatibility
.equ TWAM2 = 3 ;
.equ TWAMR2 = TWAM2 ; For compatibility
.equ TWAM3 = 4 ;
.equ TWAMR3 = TWAM3 ; For compatibility
.equ TWAM4 = 5 ;
.equ TWAMR4 = TWAM4 ; For compatibility
.equ TWAM5 = 6 ;
.equ TWAMR5 = TWAM5 ; For compatibility
.equ TWAM6 = 7 ;
.equ TWAMR6 = TWAM6 ; For compatibility

; TWBR - TWI Bit Rate register
.equ TWBR0 = 0 ;
.equ TWBR1 = 1 ;
.equ TWBR2 = 2 ;
.equ TWBR3 = 3 ;
.equ TWBR4 = 4 ;
.equ TWBR5 = 5 ;
.equ TWBR6 = 6 ;
.equ TWBR7 = 7 ;

; TWCR - TWI Control Register
.equ TWIE = 0 ; TWI Interrupt Enable
.equ TWEN = 2 ; TWI Enable Bit
.equ TWWC = 3 ; TWI Write Collition Flag
.equ TWSTO = 4 ; TWI Stop Condition Bit
.equ TWSTA = 5 ; TWI Start Condition Bit
.equ TWEA = 6 ; TWI Enable Acknowledge Bit
.equ TWINT = 7 ; TWI Interrupt Flag

; TWSR - TWI Status Register
.equ TWPS0 = 0 ; TWI Prescaler
.equ TWPS1 = 1 ; TWI Prescaler
.equ TWS3 = 3 ; TWI Status
.equ TWS4 = 4 ; TWI Status
.equ TWS5 = 5 ; TWI Status
.equ TWS6 = 6 ; TWI Status
.equ TWS7 = 7 ; TWI Status

; TWDR - TWI Data register
.equ TWD0 = 0 ; TWI Data Register Bit 0
.equ TWD1 = 1 ; TWI Data Register Bit 1
.equ TWD2 = 2 ; TWI Data Register Bit 2
.equ TWD3 = 3 ; TWI Data Register Bit 3
.equ TWD4 = 4 ; TWI Data Register Bit 4
.equ TWD5 = 5 ; TWI Data Register Bit 5
.equ TWD6 = 6 ; TWI Data Register Bit 6
.equ TWD7 = 7 ; TWI Data Register Bit 7

; TWAR - TWI (Slave) Address register
.equ TWGCE = 0 ; TWI General Call Recognition Enable Bit
.equ TWA0 = 1 ; TWI (Slave) Address register Bit 0
.equ TWA1 = 2 ; TWI (Slave) Address register Bit 1
.equ TWA2 = 3 ; TWI (Slave) Address register Bit 2
.equ TWA3 = 4 ; TWI (Slave) Address register Bit 3
.equ TWA4 = 5 ; TWI (Slave) Address register Bit 4
.equ TWA5 = 6 ; TWI (Slave) Address register Bit 5
.equ TWA6 = 7 ; TWI (Slave) Address register Bit 6


; ***** TIMER_COUNTER_1 **************
; TIMSK1 - Timer/Counter Interrupt Mask Register
.equ TOIE1 = 0 ; Timer/Counter1 Overflow Interrupt Enable
.equ OCIE1A = 1 ; Timer/Counter1 Output CompareA Match Interrupt Enable
.equ OCIE1B = 2 ; Timer/Counter1 Output CompareB Match Interrupt Enable
.equ ICIE1 = 5 ; Timer/Counter1 Input Capture Interrupt Enable

; TIFR1 - Timer/Counter Interrupt Flag register
.equ TOV1 = 0 ; Timer/Counter1 Overflow Flag
.equ OCF1A = 1 ; Output Compare Flag 1A
.equ OCF1B = 2 ; Output Compare Flag 1B
.equ ICF1 = 5 ; Input Capture Flag 1

; TCCR1A - Timer/Counter1 Control Register A
.equ WGM10 = 0 ; Waveform Generation Mode
.equ WGM11 = 1 ; Waveform Generation Mode
.equ COM1B0 = 4 ; Compare Output Mode 1B, bit 0
.equ COM1B1 = 5 ; Compare Output Mode 1B, bit 1
.equ COM1A0 = 6 ; Comparet Ouput Mode 1A, bit 0
.equ COM1A1 = 7 ; Compare Output Mode 1A, bit 1

; TCCR1B - Timer/Counter1 Control Register B
.equ CS10 = 0 ; Prescaler source of Timer/Counter 1
.equ CS11 = 1 ; Prescaler source of Timer/Counter 1
.equ CS12 = 2 ; Prescaler source of Timer/Counter 1
.equ WGM12 = 3 ; Waveform Generation Mode
.equ WGM13 = 4 ; Waveform Generation Mode
.equ ICES1 = 6 ; Input Capture 1 Edge Select
.equ ICNC1 = 7 ; Input Capture 1 Noise Canceler

; TCCR1C - Timer/Counter1 Control Register C
.equ FOC1B = 6 ;
.equ FOC1A = 7 ;

; GTCCR - General Timer/Counter Control Register
.equ PSRSYNC = 0 ; Prescaler Reset Timer/Counter1 and Timer/Counter0
.equ TSM = 7 ; Timer/Counter Synchronization Mode


; ***** TIMER_COUNTER_2 **************
; TIMSK2 - Timer/Counter Interrupt Mask register
.equ TOIE2 = 0 ; Timer/Counter2 Overflow Interrupt Enable
.equ TOIE2A = TOIE2 ; For compatibility
.equ OCIE2A = 1 ; Timer/Counter2 Output Compare Match A Interrupt Enable
.equ OCIE2B = 2 ; Timer/Counter2 Output Compare Match B Interrupt Enable

; TIFR2 - Timer/Counter Interrupt Flag Register
.equ TOV2 = 0 ; Timer/Counter2 Overflow Flag
.equ OCF2A = 1 ; Output Compare Flag 2A
.equ OCF2B = 2 ; Output Compare Flag 2B

; TCCR2A - Timer/Counter2 Control Register A
.equ WGM20 = 0 ; Waveform Genration Mode
.equ WGM21 = 1 ; Waveform Genration Mode
.equ COM2B0 = 4 ; Compare Output Mode bit 0
.equ COM2B1 = 5 ; Compare Output Mode bit 1
.equ COM2A0 = 6 ; Compare Output Mode bit 1
.equ COM2A1 = 7 ; Compare Output Mode bit 1

; TCCR2B - Timer/Counter2 Control Register B
.equ CS20 = 0 ; Clock Select bit 0
.equ CS21 = 1 ; Clock Select bit 1
.equ CS22 = 2 ; Clock Select bit 2
.equ WGM22 = 3 ; Waveform Generation Mode
.equ FOC2B = 6 ; Force Output Compare B
.equ FOC2A = 7 ; Force Output Compare A

; TCNT2 - Timer/Counter2
.equ TCNT2_0 = 0 ; Timer/Counter 2 bit 0
.equ TCNT2_1 = 1 ; Timer/Counter 2 bit 1
.equ TCNT2_2 = 2 ; Timer/Counter 2 bit 2
.equ TCNT2_3 = 3 ; Timer/Counter 2 bit 3
.equ TCNT2_4 = 4 ; Timer/Counter 2 bit 4
.equ TCNT2_5 = 5 ; Timer/Counter 2 bit 5
.equ TCNT2_6 = 6 ; Timer/Counter 2 bit 6
.equ TCNT2_7 = 7 ; Timer/Counter 2 bit 7

; OCR2A - Timer/Counter2 Output Compare Register A
.equ OCR2A_0 = 0 ; Timer/Counter2 Output Compare Register Bit 0
.equ OCR2A_1 = 1 ; Timer/Counter2 Output Compare Register Bit 1
.equ OCR2A_2 = 2 ; Timer/Counter2 Output Compare Register Bit 2
.equ OCR2A_3 = 3 ; Timer/Counter2 Output Compare Register Bit 3
.equ OCR2A_4 = 4 ; Timer/Counter2 Output Compare Register Bit 4
.equ OCR2A_5 = 5 ; Timer/Counter2 Output Compare Register Bit 5
.equ OCR2A_6 = 6 ; Timer/Counter2 Output Compare Register Bit 6
.equ OCR2A_7 = 7 ; Timer/Counter2 Output Compare Register Bit 7

; OCR2B - Timer/Counter2 Output Compare Register B
.equ OCR2B_0 = 0 ; Timer/Counter2 Output Compare Register Bit 0
.equ OCR2B_1 = 1 ; Timer/Counter2 Output Compare Register Bit 1
.equ OCR2B_2 = 2 ; Timer/Counter2 Output Compare Register Bit 2
.equ OCR2B_3 = 3 ; Timer/Counter2 Output Compare Register Bit 3
.equ OCR2B_4 = 4 ; Timer/Counter2 Output Compare Register Bit 4
.equ OCR2B_5 = 5 ; Timer/Counter2 Output Compare Register Bit 5
.equ OCR2B_6 = 6 ; Timer/Counter2 Output Compare Register Bit 6
.equ OCR2B_7 = 7 ; Timer/Counter2 Output Compare Register Bit 7

; ASSR - Asynchronous Status Register
.equ TCR2BUB = 0 ; Timer/Counter Control Register2 Update Busy
.equ TCR2AUB = 1 ; Timer/Counter Control Register2 Update Busy
.equ OCR2BUB = 2 ; Output Compare Register 2 Update Busy
.equ OCR2AUB = 3 ; Output Compare Register2 Update Busy
.equ TCN2UB = 4 ; Timer/Counter2 Update Busy
.equ AS2 = 5 ; Asynchronous Timer/Counter2
.equ EXCLK = 6 ; Enable External Clock Input

; GTCCR - General Timer Counter Control register
.equ PSRASY = 1 ; Prescaler Reset Timer/Counter2
.equ PSR2 = PSRASY ; For compatibility
;.equ TSM = 7 ; Timer/Counter Synchronization Mode


; ***** AD_CONVERTER *****************
; ADMUX - The ADC multiplexer Selection Register
.equ MUX0 = 0 ; Analog Channel and Gain Selection Bits
.equ MUX1 = 1 ; Analog Channel and Gain Selection Bits
.equ MUX2 = 2 ; Analog Channel and Gain Selection Bits
.equ MUX3 = 3 ; Analog Channel and Gain Selection Bits
.equ ADLAR = 5 ; Left Adjust Result
.equ REFS0 = 6 ; Reference Selection Bit 0
.equ REFS1 = 7 ; Reference Selection Bit 1

; ADCSRA - The ADC Control and Status register A
.equ ADPS0 = 0 ; ADC Prescaler Select Bits
.equ ADPS1 = 1 ; ADC Prescaler Select Bits
.equ ADPS2 = 2 ; ADC Prescaler Select Bits
.equ ADIE = 3 ; ADC Interrupt Enable
.equ ADIF = 4 ; ADC Interrupt Flag
.equ ADATE = 5 ; ADC Auto Trigger Enable
.equ ADSC = 6 ; ADC Start Conversion
.equ ADEN = 7 ; ADC Enable

; ADCSRB - The ADC Control and Status register B
.equ ADTS0 = 0 ; ADC Auto Trigger Source bit 0
.equ ADTS1 = 1 ; ADC Auto Trigger Source bit 1
.equ ADTS2 = 2 ; ADC Auto Trigger Source bit 2
.equ ACME = 6 ;

; ADCH - ADC Data Register High Byte
.equ ADCH0 = 0 ; ADC Data Register High Byte Bit 0
.equ ADCH1 = 1 ; ADC Data Register High Byte Bit 1
.equ ADCH2 = 2 ; ADC Data Register High Byte Bit 2
.equ ADCH3 = 3 ; ADC Data Register High Byte Bit 3
.equ ADCH4 = 4 ; ADC Data Register High Byte Bit 4
.equ ADCH5 = 5 ; ADC Data Register High Byte Bit 5
.equ ADCH6 = 6 ; ADC Data Register High Byte Bit 6
.equ ADCH7 = 7 ; ADC Data Register High Byte Bit 7

; ADCL - ADC Data Register Low Byte
.equ ADCL0 = 0 ; ADC Data Register Low Byte Bit 0
.equ ADCL1 = 1 ; ADC Data Register Low Byte Bit 1
.equ ADCL2 = 2 ; ADC Data Register Low Byte Bit 2
.equ ADCL3 = 3 ; ADC Data Register Low Byte Bit 3
.equ ADCL4 = 4 ; ADC Data Register Low Byte Bit 4
.equ ADCL5 = 5 ; ADC Data Register Low Byte Bit 5
.equ ADCL6 = 6 ; ADC Data Register Low Byte Bit 6
.equ ADCL7 = 7 ; ADC Data Register Low Byte Bit 7

; DIDR0 - Digital Input Disable Register
.equ ADC0D = 0 ;
.equ ADC1D = 1 ;
.equ ADC2D = 2 ;
.equ ADC3D = 3 ;
.equ ADC4D = 4 ;
.equ ADC5D = 5 ;


; ***** ANALOG_COMPARATOR ************
; ACSR - Analog Comparator Control And Status Register
.equ ACIS0 = 0 ; Analog Comparator Interrupt Mode Select bit 0
.equ ACIS1 = 1 ; Analog Comparator Interrupt Mode Select bit 1
.equ ACIC = 2 ; Analog Comparator Input Capture Enable
.equ ACIE = 3 ; Analog Comparator Interrupt Enable
.equ ACI = 4 ; Analog Comparator Interrupt Flag
.equ ACO = 5 ; Analog Compare Output
.equ ACBG = 6 ; Analog Comparator Bandgap Select
.equ ACD = 7 ; Analog Comparator Disable

; DIDR1 - Digital Input Disable Register 1
.equ AIN0D = 0 ; AIN0 Digital Input Disable
.equ AIN1D = 1 ; AIN1 Digital Input Disable


; ***** PORTB ************************
; PORTB - Port B Data Register
.equ PORTB0 = 0 ; Port B Data Register bit 0
.equ PB0 = 0 ; For compatibility
.equ PORTB1 = 1 ; Port B Data Register bit 1
.equ PB1 = 1 ; For compatibility
.equ PORTB2 = 2 ; Port B Data Register bit 2
.equ PB2 = 2 ; For compatibility
.equ PORTB3 = 3 ; Port B Data Register bit 3
.equ PB3 = 3 ; For compatibility
.equ PORTB4 = 4 ; Port B Data Register bit 4
.equ PB4 = 4 ; For compatibility
.equ PORTB5 = 5 ; Port B Data Register bit 5
.equ PB5 = 5 ; For compatibility
.equ PORTB6 = 6 ; Port B Data Register bit 6
.equ PB6 = 6 ; For compatibility
.equ PORTB7 = 7 ; Port B Data Register bit 7
.equ PB7 = 7 ; For compatibility

; DDRB - Port B Data Direction Register
.equ DDB0 = 0 ; Port B Data Direction Register bit 0
.equ DDB1 = 1 ; Port B Data Direction Register bit 1
.equ DDB2 = 2 ; Port B Data Direction Register bit 2
.equ DDB3 = 3 ; Port B Data Direction Register bit 3
.equ DDB4 = 4 ; Port B Data Direction Register bit 4
.equ DDB5 = 5 ; Port B Data Direction Register bit 5
.equ DDB6 = 6 ; Port B Data Direction Register bit 6
.equ DDB7 = 7 ; Port B Data Direction Register bit 7

; PINB - Port B Input Pins
.equ PINB0 = 0 ; Port B Input Pins bit 0
.equ PINB1 = 1 ; Port B Input Pins bit 1
.equ PINB2 = 2 ; Port B Input Pins bit 2
.equ PINB3 = 3 ; Port B Input Pins bit 3
.equ PINB4 = 4 ; Port B Input Pins bit 4
.equ PINB5 = 5 ; Port B Input Pins bit 5
.equ PINB6 = 6 ; Port B Input Pins bit 6
.equ PINB7 = 7 ; Port B Input Pins bit 7


; ***** PORTC ************************
; PORTC - Port C Data Register
.equ PORTC0 = 0 ; Port C Data Register bit 0
.equ PC0 = 0 ; For compatibility
.equ PORTC1 = 1 ; Port C Data Register bit 1
.equ PC1 = 1 ; For compatibility
.equ PORTC2 = 2 ; Port C Data Register bit 2
.equ PC2 = 2 ; For compatibility
.equ PORTC3 = 3 ; Port C Data Register bit 3
.equ PC3 = 3 ; For compatibility
.equ PORTC4 = 4 ; Port C Data Register bit 4
.equ PC4 = 4 ; For compatibility
.equ PORTC5 = 5 ; Port C Data Register bit 5
.equ PC5 = 5 ; For compatibility
.equ PORTC6 = 6 ; Port C Data Register bit 6
.equ PC6 = 6 ; For compatibility

; DDRC - Port C Data Direction Register
.equ DDC0 = 0 ; Port C Data Direction Register bit 0
.equ DDC1 = 1 ; Port C Data Direction Register bit 1
.equ DDC2 = 2 ; Port C Data Direction Register bit 2
.equ DDC3 = 3 ; Port C Data Direction Register bit 3
.equ DDC4 = 4 ; Port C Data Direction Register bit 4
.equ DDC5 = 5 ; Port C Data Direction Register bit 5
.equ DDC6 = 6 ; Port C Data Direction Register bit 6

; PINC - Port C Input Pins
.equ PINC0 = 0 ; Port C Input Pins bit 0
.equ PINC1 = 1 ; Port C Input Pins bit 1
.equ PINC2 = 2 ; Port C Input Pins bit 2
.equ PINC3 = 3 ; Port C Input Pins bit 3
.equ PINC4 = 4 ; Port C Input Pins bit 4
.equ PINC5 = 5 ; Port C Input Pins bit 5
.equ PINC6 = 6 ; Port C Input Pins bit 6


; ***** PORTD ************************
; PORTD - Port D Data Register
.equ PORTD0 = 0 ; Port D Data Register bit 0
.equ PD0 = 0 ; For compatibility
.equ PORTD1 = 1 ; Port D Data Register bit 1
.equ PD1 = 1 ; For compatibility
.equ PORTD2 = 2 ; Port D Data Register bit 2
.equ PD2 = 2 ; For compatibility
.equ PORTD3 = 3 ; Port D Data Register bit 3
.equ PD3 = 3 ; For compatibility
.equ PORTD4 = 4 ; Port D Data Register bit 4
.equ PD4 = 4 ; For compatibility
.equ PORTD5 = 5 ; Port D Data Register bit 5
.equ PD5 = 5 ; For compatibility
.equ PORTD6 = 6 ; Port D Data Register bit 6
.equ PD6 = 6 ; For compatibility
.equ PORTD7 = 7 ; Port D Data Register bit 7
.equ PD7 = 7 ; For compatibility

; DDRD - Port D Data Direction Register
.equ DDD0 = 0 ; Port D Data Direction Register bit 0
.equ DDD1 = 1 ; Port D Data Direction Register bit 1
.equ DDD2 = 2 ; Port D Data Direction Register bit 2
.equ DDD3 = 3 ; Port D Data Direction Register bit 3
.equ DDD4 = 4 ; Port D Data Direction Register bit 4
.equ DDD5 = 5 ; Port D Data Direction Register bit 5
.equ DDD6 = 6 ; Port D Data Direction Register bit 6
.equ DDD7 = 7 ; Port D Data Direction Register bit 7

; PIND - Port D Input Pins
.equ PIND0 = 0 ; Port D Input Pins bit 0
.equ PIND1 = 1 ; Port D Input Pins bit 1
.equ PIND2 = 2 ; Port D Input Pins bit 2
.equ PIND3 = 3 ; Port D Input Pins bit 3
.equ PIND4 = 4 ; Port D Input Pins bit 4
.equ PIND5 = 5 ; Port D Input Pins bit 5
.equ PIND6 = 6 ; Port D Input Pins bit 6
.equ PIND7 = 7 ; Port D Input Pins bit 7


; ***** TIMER_COUNTER_0 **************
; TIMSK0 - Timer/Counter0 Interrupt Mask Register
.equ TOIE0 = 0 ; Timer/Counter0 Overflow Interrupt Enable
.equ OCIE0A = 1 ; Timer/Counter0 Output Compare Match A Interrupt Enable
.equ OCIE0B = 2 ; Timer/Counter0 Output Compare Match B Interrupt Enable

; TIFR0 - Timer/Counter0 Interrupt Flag register
.equ TOV0 = 0 ; Timer/Counter0 Overflow Flag
.equ OCF0A = 1 ; Timer/Counter0 Output Compare Flag 0A
.equ OCF0B = 2 ; Timer/Counter0 Output Compare Flag 0B

; TCCR0A - Timer/Counter Control Register A
.equ WGM00 = 0 ; Waveform Generation Mode
.equ WGM01 = 1 ; Waveform Generation Mode
.equ COM0B0 = 4 ; Compare Output Mode, Fast PWm
.equ COM0B1 = 5 ; Compare Output Mode, Fast PWm
.equ COM0A0 = 6 ; Compare Output Mode, Phase Correct PWM Mode
.equ COM0A1 = 7 ; Compare Output Mode, Phase Correct PWM Mode

; TCCR0B - Timer/Counter Control Register B
.equ CS00 = 0 ; Clock Select
.equ CS01 = 1 ; Clock Select
.equ CS02 = 2 ; Clock Select
.equ WGM02 = 3 ;
.equ FOC0B = 6 ; Force Output Compare B
.equ FOC0A = 7 ; Force Output Compare A

; TCNT0 - Timer/Counter0
.equ TCNT0_0 = 0 ;
.equ TCNT0_1 = 1 ;
.equ TCNT0_2 = 2 ;
.equ TCNT0_3 = 3 ;
.equ TCNT0_4 = 4 ;
.equ TCNT0_5 = 5 ;
.equ TCNT0_6 = 6 ;
.equ TCNT0_7 = 7 ;

; OCR0A - Timer/Counter0 Output Compare Register
.equ OCR0A_0 = 0 ;
.equ OCR0A_1 = 1 ;
.equ OCR0A_2 = 2 ;
.equ OCR0A_3 = 3 ;
.equ OCR0A_4 = 4 ;
.equ OCR0A_5 = 5 ;
.equ OCR0A_6 = 6 ;
.equ OCR0A_7 = 7 ;

; OCR0B - Timer/Counter0 Output Compare Register
.equ OCR0B_0 = 0 ;
.equ OCR0B_1 = 1 ;
.equ OCR0B_2 = 2 ;
.equ OCR0B_3 = 3 ;
.equ OCR0B_4 = 4 ;
.equ OCR0B_5 = 5 ;
.equ OCR0B_6 = 6 ;
.equ OCR0B_7 = 7 ;

; GTCCR - General Timer/Counter Control Register
;.equ PSRSYNC = 0 ; Prescaler Reset Timer/Counter1 and Timer/Counter0
.equ PSR10 = PSRSYNC ; For compatibility
;.equ TSM = 7 ; Timer/Counter Synchronization Mode


; ***** EXTERNAL_INTERRUPT ***********
; EICRA - External Interrupt Control Register
.equ ISC00 = 0 ; External Interrupt Sense Control 0 Bit 0
.equ ISC01 = 1 ; External Interrupt Sense Control 0 Bit 1
.equ ISC10 = 2 ; External Interrupt Sense Control 1 Bit 0
.equ ISC11 = 3 ; External Interrupt Sense Control 1 Bit 1

; EIMSK - External Interrupt Mask Register
.equ INT0 = 0 ; External Interrupt Request 0 Enable
.equ INT1 = 1 ; External Interrupt Request 1 Enable

; EIFR - External Interrupt Flag Register
.equ INTF0 = 0 ; External Interrupt Flag 0
.equ INTF1 = 1 ; External Interrupt Flag 1

; PCICR - Pin Change Interrupt Control Register
.equ PCIE0 = 0 ; Pin Change Interrupt Enable 0
.equ PCIE1 = 1 ; Pin Change Interrupt Enable 1
.equ PCIE2 = 2 ; Pin Change Interrupt Enable 2

; PCMSK2 - Pin Change Mask Register 2
.equ PCINT16 = 0 ; Pin Change Enable Mask 16
.equ PCINT17 = 1 ; Pin Change Enable Mask 17
.equ PCINT18 = 2 ; Pin Change Enable Mask 18
.equ PCINT19 = 3 ; Pin Change Enable Mask 19
.equ PCINT20 = 4 ; Pin Change Enable Mask 20
.equ PCINT21 = 5 ; Pin Change Enable Mask 21
.equ PCINT22 = 6 ; Pin Change Enable Mask 22
.equ PCINT23 = 7 ; Pin Change Enable Mask 23

; PCMSK1 - Pin Change Mask Register 1
.equ PCINT8 = 0 ; Pin Change Enable Mask 8
.equ PCINT9 = 1 ; Pin Change Enable Mask 9
.equ PCINT10 = 2 ; Pin Change Enable Mask 10
.equ PCINT11 = 3 ; Pin Change Enable Mask 11
.equ PCINT12 = 4 ; Pin Change Enable Mask 12
.equ PCINT13 = 5 ; Pin Change Enable Mask 13
.equ PCINT14 = 6 ; Pin Change Enable Mask 14

; PCMSK0 - Pin Change Mask Register 0
.equ PCINT0 = 0 ; Pin Change Enable Mask 0
.equ PCINT1 = 1 ; Pin Change Enable Mask 1
.equ PCINT2 = 2 ; Pin Change Enable Mask 2
.equ PCINT3 = 3 ; Pin Change Enable Mask 3
.equ PCINT4 = 4 ; Pin Change Enable Mask 4
.equ PCINT5 = 5 ; Pin Change Enable Mask 5
.equ PCINT6 = 6 ; Pin Change Enable Mask 6
.equ PCINT7 = 7 ; Pin Change Enable Mask 7

; PCIFR - Pin Change Interrupt Flag Register
.equ PCIF0 = 0 ; Pin Change Interrupt Flag 0
.equ PCIF1 = 1 ; Pin Change Interrupt Flag 1
.equ PCIF2 = 2 ; Pin Change Interrupt Flag 2


; ***** SPI **************************
; SPDR - SPI Data Register
.equ SPDR0 = 0 ; SPI Data Register bit 0
.equ SPDR1 = 1 ; SPI Data Register bit 1
.equ SPDR2 = 2 ; SPI Data Register bit 2
.equ SPDR3 = 3 ; SPI Data Register bit 3
.equ SPDR4 = 4 ; SPI Data Register bit 4
.equ SPDR5 = 5 ; SPI Data Register bit 5
.equ SPDR6 = 6 ; SPI Data Register bit 6
.equ SPDR7 = 7 ; SPI Data Register bit 7

; SPSR - SPI Status Register
.equ SPI2X = 0 ; Double SPI Speed Bit
.equ WCOL = 6 ; Write Collision Flag
.equ SPIF = 7 ; SPI Interrupt Flag

; SPCR - SPI Control Register
.equ SPR0 = 0 ; SPI Clock Rate Select 0
.equ SPR1 = 1 ; SPI Clock Rate Select 1
.equ CPHA = 2 ; Clock Phase
.equ CPOL = 3 ; Clock polarity
.equ MSTR = 4 ; Master/Slave Select
.equ DORD = 5 ; Data Order
.equ SPE = 6 ; SPI Enable
.equ SPIE = 7 ; SPI Interrupt Enable


; ***** WATCHDOG *********************
; WDTCSR - Watchdog Timer Control Register
.equ WDP0 = 0 ; Watch Dog Timer Prescaler bit 0
.equ WDP1 = 1 ; Watch Dog Timer Prescaler bit 1
.equ WDP2 = 2 ; Watch Dog Timer Prescaler bit 2
.equ WDE = 3 ; Watch Dog Enable
.equ WDCE = 4 ; Watchdog Change Enable
.equ WDP3 = 5 ; Watchdog Timer Prescaler Bit 3
.equ WDIE = 6 ; Watchdog Timeout Interrupt Enable
.equ WDIF = 7 ; Watchdog Timeout Interrupt Flag


; ***** CPU **************************
; SREG - Status Register
.equ SREG_C = 0 ; Carry Flag
.equ SREG_Z = 1 ; Zero Flag
.equ SREG_N = 2 ; Negative Flag
.equ SREG_V = 3 ; Two's Complement Overflow Flag
.equ SREG_S = 4 ; Sign Bit
.equ SREG_H = 5 ; Half Carry Flag
.equ SREG_T = 6 ; Bit Copy Storage
.equ SREG_I = 7 ; Global Interrupt Enable

; OSCCAL - Oscillator Calibration Value
.equ CAL0 = 0 ; Oscillator Calibration Value Bit0
.equ CAL1 = 1 ; Oscillator Calibration Value Bit1
.equ CAL2 = 2 ; Oscillator Calibration Value Bit2
.equ CAL3 = 3 ; Oscillator Calibration Value Bit3
.equ CAL4 = 4 ; Oscillator Calibration Value Bit4
.equ CAL5 = 5 ; Oscillator Calibration Value Bit5
.equ CAL6 = 6 ; Oscillator Calibration Value Bit6
.equ CAL7 = 7 ; Oscillator Calibration Value Bit7

; CLKPR - Clock Prescale Register
.equ CLKPS0 = 0 ; Clock Prescaler Select Bit 0
.equ CLKPS1 = 1 ; Clock Prescaler Select Bit 1
.equ CLKPS2 = 2 ; Clock Prescaler Select Bit 2
.equ CLKPS3 = 3 ; Clock Prescaler Select Bit 3
.equ CLKPCE = 7 ; Clock Prescaler Change Enable

; SPMCSR - Store Program Memory Control and Status Register
.equ SELFPRGEN = 0; Added for backwards compatibility
.equ SPMEN = 0 ; Store Program Memory
.equ PGERS = 1 ; Page Erase
.equ PGWRT = 2 ; Page Write
.equ BLBSET = 3 ; Boot Lock Bit Set
.equ RWWSRE = 4 ; Read-While-Write section read enable
.equ SIGRD = 5 ; Signature Row Read
.equ RWWSB = 6 ; Read-While-Write Section Busy
.equ SPMIE = 7 ; SPM Interrupt Enable

; MCUCR - MCU Control Register
.equ IVCE = 0 ;
.equ IVSEL = 1 ;
.equ PUD = 4 ;
.equ BODSE = 5 ; BOD Sleep Enable
.equ BODS = 6 ; BOD Sleep

; MCUSR - MCU Status Register
.equ PORF = 0 ; Power-on reset flag
.equ EXTRF = 1 ; External Reset Flag
.equ EXTREF = EXTRF ; For compatibility
.equ BORF = 2 ; Brown-out Reset Flag
.equ WDRF = 3 ; Watchdog Reset Flag

; SMCR - Sleep Mode Control Register
.equ SE = 0 ; Sleep Enable
.equ SM0 = 1 ; Sleep Mode Select Bit 0
.equ SM1 = 2 ; Sleep Mode Select Bit 1
.equ SM2 = 3 ; Sleep Mode Select Bit 2

; GPIOR2 - General Purpose I/O Register 2
.equ GPIOR20 = 0 ;
.equ GPIOR21 = 1 ;
.equ GPIOR22 = 2 ;
.equ GPIOR23 = 3 ;
.equ GPIOR24 = 4 ;
.equ GPIOR25 = 5 ;
.equ GPIOR26 = 6 ;
.equ GPIOR27 = 7 ;

; GPIOR1 - General Purpose I/O Register 1
.equ GPIOR10 = 0 ;
.equ GPIOR11 = 1 ;
.equ GPIOR12 = 2 ;
.equ GPIOR13 = 3 ;
.equ GPIOR14 = 4 ;
.equ GPIOR15 = 5 ;
.equ GPIOR16 = 6 ;
.equ GPIOR17 = 7 ;

; GPIOR0 - General Purpose I/O Register 0
.equ GPIOR00 = 0 ;
.equ GPIOR01 = 1 ;
.equ GPIOR02 = 2 ;
.equ GPIOR03 = 3 ;
.equ GPIOR04 = 4 ;
.equ GPIOR05 = 5 ;
.equ GPIOR06 = 6 ;
.equ GPIOR07 = 7 ;

; PRR - Power Reduction Register
.equ PRADC = 0 ; Power Reduction ADC
.equ PRUSART0 = 1 ; Power Reduction USART
.equ PRSPI = 2 ; Power Reduction Serial Peripheral Interface
.equ PRTIM1 = 3 ; Power Reduction Timer/Counter1
.equ PRTIM0 = 5 ; Power Reduction Timer/Counter0
.equ PRTIM2 = 6 ; Power Reduction Timer/Counter2
.equ PRTWI = 7 ; Power Reduction TWI


; ***** EEPROM ***********************
; EEARL - EEPROM Address Register Low Byte
.equ EEAR0 = 0 ; EEPROM Read/Write Access Bit 0
.equ EEAR1 = 1 ; EEPROM Read/Write Access Bit 1
.equ EEAR2 = 2 ; EEPROM Read/Write Access Bit 2
.equ EEAR3 = 3 ; EEPROM Read/Write Access Bit 3
.equ EEAR4 = 4 ; EEPROM Read/Write Access Bit 4
.equ EEAR5 = 5 ; EEPROM Read/Write Access Bit 5
.equ EEAR6 = 6 ; EEPROM Read/Write Access Bit 6
.equ EEAR7 = 7 ; EEPROM Read/Write Access Bit 7

; EEARH - EEPROM Address Register High Byte
.equ EEAR8 = 0 ; EEPROM Read/Write Access Bit 8
.equ EEAR9 = 1 ; EEPROM Read/Write Access Bit 9

; EEDR - EEPROM Data Register
.equ EEDR0 = 0 ; EEPROM Data Register bit 0
.equ EEDR1 = 1 ; EEPROM Data Register bit 1
.equ EEDR2 = 2 ; EEPROM Data Register bit 2
.equ EEDR3 = 3 ; EEPROM Data Register bit 3
.equ EEDR4 = 4 ; EEPROM Data Register bit 4
.equ EEDR5 = 5 ; EEPROM Data Register bit 5
.equ EEDR6 = 6 ; EEPROM Data Register bit 6
.equ EEDR7 = 7 ; EEPROM Data Register bit 7

; EECR - EEPROM Control Register
.equ EERE = 0 ; EEPROM Read Enable
.equ EEPE = 1 ; EEPROM Write Enable
.equ EEMPE = 2 ; EEPROM Master Write Enable
.equ EERIE = 3 ; EEPROM Ready Interrupt Enable
.equ EEPM0 = 4 ; EEPROM Programming Mode Bit 0
.equ EEPM1 = 5 ; EEPROM Programming Mode Bit 1



; ***** LOCKSBITS ********************************************************
.equ LB1 = 0 ; Lock bit
.equ LB2 = 1 ; Lock bit
.equ BLB01 = 2 ; Boot Lock bit
.equ BLB02 = 3 ; Boot Lock bit
.equ BLB11 = 4 ; Boot lock bit
.equ BLB12 = 5 ; Boot lock bit


; ***** FUSES ************************************************************
; LOW fuse bits
.equ CKSEL0 = 0 ; Select Clock Source
.equ CKSEL1 = 1 ; Select Clock Source
.equ CKSEL2 = 2 ; Select Clock Source
.equ CKSEL3 = 3 ; Select Clock Source
.equ SUT0 = 4 ; Select start-up time
.equ SUT1 = 5 ; Select start-up time
.equ CKOUT = 6 ; Clock output
.equ CKDIV8 = 7 ; Divide clock by 8

; HIGH fuse bits
.equ BOOTRST = 0 ; Select reset vector
.equ BOOTSZ0 = 1 ; Select boot size
.equ BOOTSZ1 = 2 ; Select boot size
.equ EESAVE = 3 ; EEPROM memory is preserved through chip erase
.equ WDTON = 4 ; Watchdog Timer Always On
.equ SPIEN = 5 ; Enable Serial programming and Data Downloading
.equ DWEN = 6 ; debugWIRE Enable
.equ RSTDISBL = 7 ; External reset disable

; EXTENDED fuse bits
.equ BODLEVEL0 = 0 ; Brown-out Detector trigger level
.equ BODLEVEL1 = 1 ; Brown-out Detector trigger level
.equ BODLEVEL2 = 2 ; Brown-out Detector trigger level



; ***** CPU REGISTER DEFINITIONS *****************************************
.def XH = r27
.def XL = r26
.def YH = r29
.def YL = r28
.def ZH = r31
.def ZL = r30



; ***** DATA MEMORY DECLARATIONS *****************************************
.equ FLASHEND = 0x3fff ; Note: Word address
.equ IOEND = 0x00ff
.equ SRAM_START = 0x0100
.equ SRAM_SIZE = 2048
.equ RAMEND = 0x08ff
.equ XRAMEND = 0x0000
.equ E2END = 0x03ff
.equ EEPROMEND = 0x03ff
.equ EEADRBITS = 10
#pragma AVRPART MEMORY PROG_FLASH 32768
#pragma AVRPART MEMORY EEPROM 1024
#pragma AVRPART MEMORY INT_SRAM SIZE 2048
#pragma AVRPART MEMORY INT_SRAM START_ADDR 0x100



; ***** BOOTLOADER DECLARATIONS ******************************************
.equ NRWW_START_ADDR = 0x3800
.equ NRWW_STOP_ADDR = 0x3fff
.equ RWW_START_ADDR = 0x0
.equ RWW_STOP_ADDR = 0x37ff
.equ PAGESIZE = 64
.equ FIRSTBOOTSTART = 0x3f00
.equ SECONDBOOTSTART = 0x3e00
.equ THIRDBOOTSTART = 0x3c00
.equ FOURTHBOOTSTART = 0x3800
.equ SMALLBOOTSTART = FIRSTBOOTSTART
.equ LARGEBOOTSTART = FOURTHBOOTSTART



; ***** INTERRUPT VECTORS ************************************************
.equ INT0addr = 0x0002 ; External Interrupt Request 0
.equ INT1addr = 0x0004 ; External Interrupt Request 1
.equ PCI0addr = 0x0006 ; Pin Change Interrupt Request 0
.equ PCI1addr = 0x0008 ; Pin Change Interrupt Request 0
.equ PCI2addr = 0x000a ; Pin Change Interrupt Request 1
.equ WDTaddr = 0x000c ; Watchdog Time-out Interrupt
.equ OC2Aaddr = 0x000e ; Timer/Counter2 Compare Match A
.equ OC2Baddr = 0x0010 ; Timer/Counter2 Compare Match A
.equ OVF2addr = 0x0012 ; Timer/Counter2 Overflow
.equ ICP1addr = 0x0014 ; Timer/Counter1 Capture Event
.equ OC1Aaddr = 0x0016 ; Timer/Counter1 Compare Match A
.equ OC1Baddr = 0x0018 ; Timer/Counter1 Compare Match B
.equ OVF1addr = 0x001a ; Timer/Counter1 Overflow
.equ OC0Aaddr = 0x001c ; TimerCounter0 Compare Match A
.equ OC0Baddr = 0x001e ; TimerCounter0 Compare Match B
.equ OVF0addr = 0x0020 ; Timer/Couner0 Overflow
.equ SPIaddr = 0x0022 ; SPI Serial Transfer Complete
.equ URXCaddr = 0x0024 ; USART Rx Complete
.equ UDREaddr = 0x0026 ; USART, Data Register Empty
.equ UTXCaddr = 0x0028 ; USART Tx Complete
.equ ADCCaddr = 0x002a ; ADC Conversion Complete
.equ ERDYaddr = 0x002c ; EEPROM Ready
.equ ACIaddr = 0x002e ; Analog Comparator
.equ TWIaddr = 0x0030 ; Two-wire Serial Interface
.equ SPMRaddr = 0x0032 ; Store Program Memory Read

.equ INT_VECTORS_SIZE = 52 ; size in words

#endif /* _M328PDEF_INC_ */

; ***** END OF FILE ******************************************************

; AssemblerApplication1.asm
;
; Created: 2024/02/13 0:03:36
; Author : khaya
;


; Replace with your application code
start:
000000 9503 inc r16
000001 cffe rjmp start


RESOURCE USE INFORMATION
------------------------

Notice:
The register and instruction counts are symbol table hit counts,
and hence implicitly used resources are not counted, eg, the
'lpm' instruction without operands implicitly uses r0 and z,
none of which are counted.

x,y,z are separate entities in the symbol table and are
counted separately from r26..r31 here.

.dseg memory usage only counts static data declared with .byte

"ATmega328P" register use summary:
x : 0 y : 0 z : 0 r0 : 0 r1 : 0 r2 : 0 r3 : 0 r4 : 0
r5 : 0 r6 : 0 r7 : 0 r8 : 0 r9 : 0 r10: 0 r11: 0 r12: 0
r13: 0 r14: 0 r15: 0 r16: 1 r17: 0 r18: 0 r19: 0 r20: 0
r21: 0 r22: 0 r23: 0 r24: 0 r25: 0 r26: 0 r27: 0 r28: 0
r29: 0 r30: 0 r31: 0
Registers used: 1 out of 35 (2.9%)

"ATmega328P" instruction use summary:
.lds : 0 .sts : 0 adc : 0 add : 0 adiw : 0 and : 0
andi : 0 asr : 0 bclr : 0 bld : 0 brbc : 0 brbs : 0
brcc : 0 brcs : 0 break : 0 breq : 0 brge : 0 brhc : 0
brhs : 0 brid : 0 brie : 0 brlo : 0 brlt : 0 brmi : 0
brne : 0 brpl : 0 brsh : 0 brtc : 0 brts : 0 brvc : 0
brvs : 0 bset : 0 bst : 0 call : 0 cbi : 0 cbr : 0
clc : 0 clh : 0 cli : 0 cln : 0 clr : 0 cls : 0
clt : 0 clv : 0 clz : 0 com : 0 cp : 0 cpc : 0
cpi : 0 cpse : 0 dec : 0 eor : 0 fmul : 0 fmuls : 0
fmulsu: 0 icall : 0 ijmp : 0 in : 0 inc : 1 jmp : 0
ld : 0 ldd : 0 ldi : 0 lds : 0 lpm : 0 lsl : 0
lsr : 0 mov : 0 movw : 0 mul : 0 muls : 0 mulsu : 0
neg : 0 nop : 0 or : 0 ori : 0 out : 0 pop : 0
push : 0 rcall : 0 ret : 0 reti : 0 rjmp : 1 rol : 0
ror : 0 sbc : 0 sbci : 0 sbi : 0 sbic : 0 sbis : 0
sbiw : 0 sbr : 0 sbrc : 0 sbrs : 0 sec : 0 seh : 0
sei : 0 sen : 0 ser : 0 ses : 0 set : 0 sev : 0
sez : 0 sleep : 0 spm : 0 st : 0 std : 0 sts : 0
sub : 0 subi : 0 swap : 0 tst : 0 wdr : 0
Instructions used: 2 out of 113 (1.8%)

"ATmega328P" memory use summary [bytes]:
Segment Begin End Code Data Used Size Use%
---------------------------------------------------------------
[.cseg] 0x000000 0x000004 4 0 4 32768 0.0%
[.dseg] 0x000100 0x000100 0 0 0 2048 0.0%
[.eseg] 0x000000 0x000000 0 0 0 1024 0.0%

Assembly complete, 0 errors, 0 warnings




2024.02.13 16:58 | pmlink.png 固定リンク | folder.png その他・雑談
マイコンのアセンブリ言語を教えるには...?
いまさらアセンブラでプログラミングの演習とかやりたいわけじゃなくて、新しいハードウェアの開発環境を整えようとすると、高級言語との橋渡しとして機械語(アセンブリ言語)の知識が必要になって来るので、その辺の関係性だけ浅くでも知っておいてほしい、と思ったときに何を教材にすればよいでしょうか?

少し前なら、CASLを教えとけば、基本情報処理技術者試験ででてくるからという理由は付いたのですが、いまはCASLの試験は無くなって、言語選択さえなくなってます。

例えばx86系だとPCで何か別の言語で書いた方が気が利いてるのでわざわざアセンブリ言語で書いても面白くない。
マイコンでシェアのあるARM系かなぁと思ったけど、ちょっと大変そう。

低学年でArduinoの使い方を教えてるのでAVRマイコンのアセンブリ言語を教えて、ハードとの関連性を見てもらうというのはどうかと思いました。
AVR studio(Microchip studio)だと、C言語でプログラムを書いてビルド後にできるファイルの中に.lssファイルがあってこれをテキストで開くとアセンブリ言語になってます。
Arduinoで作業領域にいったんアセンブリ言語のプログラムが作られてないか探そうと思ったら、そもそも作業領域がどこか探すのに手間取りました。

見つけたのがこちらのサイト
https://dlna-paradise.blogspot.com/2019/06/arduinoidec.html

ここにあるように、設定の中でコンパイル時により詳細な情報を表示するようにするとコンパイル時の作業フォルダ名が表示されます。
例えば、
"C:\\Users\\ユーザ名\\AppData\\Local\\Temp\\arduino\\sketches\\932B4C1D9695F7DB71234520971B/sketch_feb13a.ino.elf"

という感じでかなり見つけにくいところにありました。
このフォルダ内を探しても、アセンブリ言語のファイルはありません。

コンパイル時にオプションでアセンブリ言語を出力するように設定しないといけないですが、その記述がどこにあるかも探すのが大変です。

最初に紹介されてる方法として、avr-objdump -S を使ってアセンブリを出力すると書いてあったので、avr-objdumpを検索したけど、これもどこにあるか分かりません。
検索して見つかったのは、PC内に保存してあった古いバージョンのArdinoのシステム一式の中のavr-objdump.exe のみ。

しょうがないのでこれで試してみました。
新規スケッチを作成。
setupもloopも空のままコンパイル。
できたelfファイルを作業しやすいフォルダにコピー。
コマンドラインを開いて、avr-objdump -S ファイル名.elf > アセンブリファイル名.S
を実行。
すると、.Sファイルが作成されてメモ帳で開くとアセンブリ言語になってます。
以下の通りですが、長いです。周辺回路の初期設定をいろいろやらないといけないようです。
プログラムの実体は、下の方の数行だと思います。






blank.elf: file format elf32-avr
Disassembly of section .text:

00000000 <__vectors>:
0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
4: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
8: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
10: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
14: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
18: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
1c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
20: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
24: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
28: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
2c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
30: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
34: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
38: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
3c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
40: 0c 94 48 00 jmp 0x90 ; 0x90 <__vector_16>
44: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
48: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
4c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
50: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
54: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
58: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
5c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
60: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>
64: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt>

00000068 <__ctors_end>:
68: 11 24 eor r1, r1
6a: 1f be out 0x3f, r1 ; 63
6c: cf ef ldi r28, 0xFF ; 255
6e: d8 e0 ldi r29, 0x08 ; 8
70: de bf out 0x3e, r29 ; 62
72: cd bf out 0x3d, r28 ; 61

00000074 <__do_clear_bss>:
74: 21 e0 ldi r18, 0x01 ; 1
76: a0 e0 ldi r26, 0x00 ; 0
78: b1 e0 ldi r27, 0x01 ; 1
7a: 01 c0 rjmp .+2 ; 0x7e <.do_clear_bss_start>

0000007c <.do_clear_bss_loop>:
7c: 1d 92 st X+, r1

0000007e <.do_clear_bss_start>:
7e: a9 30 cpi r26, 0x09 ; 9
80: b2 07 cpc r27, r18
82: e1 f7 brne .-8 ; 0x7c <.do_clear_bss_loop>
84: 0e 94 92 00 call 0x124 ; 0x124

88: 0c 94 dc 00 jmp 0x1b8 ; 0x1b8 <_exit>

0000008c <__bad_interrupt>:
8c: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>

00000090 <__vector_16>:
#if defined(TIM0_OVF_vect)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
90: 1f 92 push r1
92: 0f 92 push r0
94: 0f b6 in r0, 0x3f ; 63
96: 0f 92 push r0
98: 11 24 eor r1, r1
9a: 2f 93 push r18
9c: 3f 93 push r19
9e: 8f 93 push r24
a0: 9f 93 push r25
a2: af 93 push r26
a4: bf 93 push r27
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
a6: 80 91 05 01 lds r24, 0x0105
aa: 90 91 06 01 lds r25, 0x0106
ae: a0 91 07 01 lds r26, 0x0107
b2: b0 91 08 01 lds r27, 0x0108
unsigned char f = timer0_fract;
b6: 30 91 04 01 lds r19, 0x0104

m += MILLIS_INC;
f += FRACT_INC;
ba: 23 e0 ldi r18, 0x03 ; 3
bc: 23 0f add r18, r19
if (f >= FRACT_MAX) {
be: 2d 37 cpi r18, 0x7D ; 125
c0: 58 f5 brcc .+86 ; 0x118 <__vector_16+0x88>
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;

m += MILLIS_INC;
c2: 01 96 adiw r24, 0x01 ; 1
c4: a1 1d adc r26, r1
c6: b1 1d adc r27, r1
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}

timer0_fract = f;
c8: 20 93 04 01 sts 0x0104, r18
timer0_millis = m;
cc: 80 93 05 01 sts 0x0105, r24
d0: 90 93 06 01 sts 0x0106, r25
d4: a0 93 07 01 sts 0x0107, r26
d8: b0 93 08 01 sts 0x0108, r27
timer0_overflow_count++;
dc: 80 91 00 01 lds r24, 0x0100
e0: 90 91 01 01 lds r25, 0x0101
e4: a0 91 02 01 lds r26, 0x0102
e8: b0 91 03 01 lds r27, 0x0103
ec: 01 96 adiw r24, 0x01 ; 1
ee: a1 1d adc r26, r1
f0: b1 1d adc r27, r1
f2: 80 93 00 01 sts 0x0100, r24
f6: 90 93 01 01 sts 0x0101, r25
fa: a0 93 02 01 sts 0x0102, r26
fe: b0 93 03 01 sts 0x0103, r27
}
102: bf 91 pop r27
104: af 91 pop r26
106: 9f 91 pop r25
108: 8f 91 pop r24
10a: 3f 91 pop r19
10c: 2f 91 pop r18
10e: 0f 90 pop r0
110: 0f be out 0x3f, r0 ; 63
112: 0f 90 pop r0
114: 1f 90 pop r1
116: 18 95 reti
unsigned char f = timer0_fract;

m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
118: 26 e8 ldi r18, 0x86 ; 134
11a: 23 0f add r18, r19
m += 1;
11c: 02 96 adiw r24, 0x02 ; 2
11e: a1 1d adc r26, r1
120: b1 1d adc r27, r1
122: d2 cf rjmp .-92 ; 0xc8 <__vector_16+0x38>

00000124
:

void init()
{
// this needs to be called before setup() or some functions won't
// work there
sei();
124: 78 94 sei

// on the ATmega168, timer 0 is also used for fast hardware pwm
// (using phase-correct PWM would mean that timer 0 overflowed half as often
// resulting in different millis() behavior on the ATmega8 and ATmega168)
#if defined(TCCR0A) && defined(WGM01)
sbi(TCCR0A, WGM01);
126: 84 b5 in r24, 0x24 ; 36
128: 82 60 ori r24, 0x02 ; 2
12a: 84 bd out 0x24, r24 ; 36
sbi(TCCR0A, WGM00);
12c: 84 b5 in r24, 0x24 ; 36
12e: 81 60 ori r24, 0x01 ; 1
130: 84 bd out 0x24, r24 ; 36
// this combination is for the standard atmega8
sbi(TCCR0, CS01);
sbi(TCCR0, CS00);
#elif defined(TCCR0B) && defined(CS01) && defined(CS00)
// this combination is for the standard 168/328/1280/2560
sbi(TCCR0B, CS01);
132: 85 b5 in r24, 0x25 ; 37
134: 82 60 ori r24, 0x02 ; 2
136: 85 bd out 0x25, r24 ; 37
sbi(TCCR0B, CS00);
138: 85 b5 in r24, 0x25 ; 37
13a: 81 60 ori r24, 0x01 ; 1
13c: 85 bd out 0x25, r24 ; 37

// enable timer 0 overflow interrupt
#if defined(TIMSK) && defined(TOIE0)
sbi(TIMSK, TOIE0);
#elif defined(TIMSK0) && defined(TOIE0)
sbi(TIMSK0, TOIE0);
13e: 80 91 6e 00 lds r24, 0x006E
142: 81 60 ori r24, 0x01 ; 1
144: 80 93 6e 00 sts 0x006E, r24
// this is better for motors as it ensures an even waveform
// note, however, that fast pwm mode can achieve a frequency of up
// 8 MHz (with a 16 MHz clock) at 50% duty cycle

#if defined(TCCR1B) && defined(CS11) && defined(CS10)
TCCR1B = 0;
148: 10 92 81 00 sts 0x0081, r1

// set timer 1 prescale factor to 64
sbi(TCCR1B, CS11);
14c: 80 91 81 00 lds r24, 0x0081
150: 82 60 ori r24, 0x02 ; 2
152: 80 93 81 00 sts 0x0081, r24
#if F_CPU >= 8000000L
sbi(TCCR1B, CS10);
156: 80 91 81 00 lds r24, 0x0081
15a: 81 60 ori r24, 0x01 ; 1
15c: 80 93 81 00 sts 0x0081, r24
sbi(TCCR1, CS10);
#endif
#endif
// put timer 1 in 8-bit phase correct pwm mode
#if defined(TCCR1A) && defined(WGM10)
sbi(TCCR1A, WGM10);
160: 80 91 80 00 lds r24, 0x0080
164: 81 60 ori r24, 0x01 ; 1
166: 80 93 80 00 sts 0x0080, r24

// set timer 2 prescale factor to 64
#if defined(TCCR2) && defined(CS22)
sbi(TCCR2, CS22);
#elif defined(TCCR2B) && defined(CS22)
sbi(TCCR2B, CS22);
16a: 80 91 b1 00 lds r24, 0x00B1
16e: 84 60 ori r24, 0x04 ; 4
170: 80 93 b1 00 sts 0x00B1, r24

// configure timer 2 for phase correct pwm (8-bit)
#if defined(TCCR2) && defined(WGM20)
sbi(TCCR2, WGM20);
#elif defined(TCCR2A) && defined(WGM20)
sbi(TCCR2A, WGM20);
174: 80 91 b0 00 lds r24, 0x00B0
178: 81 60 ori r24, 0x01 ; 1
17a: 80 93 b0 00 sts 0x00B0, r24
#endif

#if defined(ADCSRA)
// set a2d prescaler so we are inside the desired 50-200 KHz range.
#if F_CPU >= 16000000 // 16 MHz / 128 = 125 KHz
sbi(ADCSRA, ADPS2);
17e: 80 91 7a 00 lds r24, 0x007A
182: 84 60 ori r24, 0x04 ; 4
184: 80 93 7a 00 sts 0x007A, r24
sbi(ADCSRA, ADPS1);
188: 80 91 7a 00 lds r24, 0x007A
18c: 82 60 ori r24, 0x02 ; 2
18e: 80 93 7a 00 sts 0x007A, r24
sbi(ADCSRA, ADPS0);
192: 80 91 7a 00 lds r24, 0x007A
196: 81 60 ori r24, 0x01 ; 1
198: 80 93 7a 00 sts 0x007A, r24
cbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
#endif
// enable a2d conversions
sbi(ADCSRA, ADEN);
19c: 80 91 7a 00 lds r24, 0x007A
1a0: 80 68 ori r24, 0x80 ; 128
1a2: 80 93 7a 00 sts 0x007A, r24
// here so they can be used as normal digital i/o; they will be
// reconnected in Serial.begin()
#if defined(UCSRB)
UCSRB = 0;
#elif defined(UCSR0B)
UCSR0B = 0;
1a6: 10 92 c1 00 sts 0x00C1, r1

setup();

for (;;) {
loop();
if (serialEventRun) serialEventRun();
1aa: c0 e0 ldi r28, 0x00 ; 0
1ac: d0 e0 ldi r29, 0x00 ; 0
1ae: 20 97 sbiw r28, 0x00 ; 0
1b0: f1 f3 breq .-4 ; 0x1ae
1b2: 0e 94 00 00 call 0 ; 0x0 <__vectors>
1b6: fb cf rjmp .-10 ; 0x1ae

000001b8 <_exit>:
1b8: f8 94 cli

000001ba <__stop_program>:
1ba: ff cf rjmp .-2 ; 0x1ba <__stop_program>





----------------------------------------------

更にdigital blinkのプログラムをアセンブラに直してみました。
LEDを点滅させるだけでも結構プログラムの行数があります。




Blink.ino.elf: file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
0: 0c 94 5c 00 jmp 0xb8 ; 0xb8 <__ctors_end>
4: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
8: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
c: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
10: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
14: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
18: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
1c: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
20: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
24: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
28: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
2c: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
30: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
34: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
38: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
3c: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
40: 0c 94 13 01 jmp 0x226 ; 0x226 <__vector_16>
44: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
48: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
4c: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
50: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
54: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
58: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
5c: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
60: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>
64: 0c 94 6e 00 jmp 0xdc ; 0xdc <__bad_interrupt>

00000068 <__trampolines_end>:
68: 00 00 nop
6a: 00 00 nop
6c: 24 00 .word 0x0024 ; ????
6e: 27 00 .word 0x0027 ; ????
70: 2a 00 .word 0x002a ; ????

00000072 :
72: 00 00 00 00 25 00 28 00 2b 00 ....%.(.+.

0000007c :
7c: 04 04 04 04 04 04 04 04 02 02 02 02 02 02 03 03 ................
8c: 03 03 03 03 ....

00000090 :
90: 01 02 04 08 10 20 40 80 01 02 04 08 10 20 01 02 ..... @...... ..
a0: 04 08 10 20 ...

000000a4 :
a4: 00 00 00 08 00 02 01 00 00 03 04 07 00 00 00 00 ................
b4: 00 00 00 00 ....

000000b8 <__ctors_end>:
b8: 11 24 eor r1, r1
ba: 1f be out 0x3f, r1 ; 63
bc: cf ef ldi r28, 0xFF ; 255
be: d8 e0 ldi r29, 0x08 ; 8
c0: de bf out 0x3e, r29 ; 62
c2: cd bf out 0x3d, r28 ; 61

000000c4 <__do_clear_bss>:
c4: 21 e0 ldi r18, 0x01 ; 1
c6: a0 e0 ldi r26, 0x00 ; 0
c8: b1 e0 ldi r27, 0x01 ; 1
ca: 01 c0 rjmp .+2 ; 0xce <.do_clear_bss_start>

000000cc <.do_clear_bss_loop>:
cc: 1d 92 st X+, r1

000000ce <.do_clear_bss_start>:
ce: a9 30 cpi r26, 0x09 ; 9
d0: b2 07 cpc r27, r18
d2: e1 f7 brne .-8 ; 0xcc <.do_clear_bss_loop>
d4: 0e 94 5d 01 call 0x2ba ; 0x2ba

d8: 0c 94 cc 01 jmp 0x398 ; 0x398 <_exit>

000000dc <__bad_interrupt>:
dc: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>

000000e0 :
}
}

void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
e0: e1 eb ldi r30, 0xB1 ; 177
e2: f0 e0 ldi r31, 0x00 ; 0
e4: 24 91 lpm r18, Z+
uint8_t bit = digitalPinToBitMask(pin);
e6: ed e9 ldi r30, 0x9D ; 157
e8: f0 e0 ldi r31, 0x00 ; 0
ea: 94 91 lpm r25, Z+
uint8_t port = digitalPinToPort(pin);
ec: e9 e8 ldi r30, 0x89 ; 137
ee: f0 e0 ldi r31, 0x00 ; 0
f0: e4 91 lpm r30, Z+
volatile uint8_t *out;

if (port == NOT_A_PIN) return;
f2: ee 23 and r30, r30
f4: c9 f0 breq .+50 ; 0x128

// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
f6: 22 23 and r18, r18
f8: 39 f0 breq .+14 ; 0x108
//
//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
//static inline void turnOffPWM(uint8_t timer)
static void turnOffPWM(uint8_t timer)
{
switch (timer)
fa: 23 30 cpi r18, 0x03 ; 3
fc: 01 f1 breq .+64 ; 0x13e
fe: a8 f4 brcc .+42 ; 0x12a
100: 21 30 cpi r18, 0x01 ; 1
102: 19 f1 breq .+70 ; 0x14a
104: 22 30 cpi r18, 0x02 ; 2
106: 29 f1 breq .+74 ; 0x152

// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);

out = portOutputRegister(port);
108: f0 e0 ldi r31, 0x00 ; 0
10a: ee 0f add r30, r30
10c: ff 1f adc r31, r31
10e: ee 58 subi r30, 0x8E ; 142
110: ff 4f sbci r31, 0xFF ; 255
112: a5 91 lpm r26, Z+
114: b4 91 lpm r27, Z+

uint8_t oldSREG = SREG;
116: 2f b7 in r18, 0x3f ; 63
cli();
118: f8 94 cli

if (val == LOW) {
*out &= ~bit;
11a: ec 91 ld r30, X
out = portOutputRegister(port);

uint8_t oldSREG = SREG;
cli();

if (val == LOW) {
11c: 81 11 cpse r24, r1
11e: 26 c0 rjmp .+76 ; 0x16c
*out &= ~bit;
120: 90 95 com r25
122: 9e 23 and r25, r30
} else {
*out |= bit;
124: 9c 93 st X, r25
}

SREG = oldSREG;
126: 2f bf out 0x3f, r18 ; 63
}
128: 08 95 ret
//
//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
//static inline void turnOffPWM(uint8_t timer)
static void turnOffPWM(uint8_t timer)
{
switch (timer)
12a: 27 30 cpi r18, 0x07 ; 7
12c: a9 f0 breq .+42 ; 0x158
12e: 28 30 cpi r18, 0x08 ; 8
130: c9 f0 breq .+50 ; 0x164
132: 24 30 cpi r18, 0x04 ; 4
134: 49 f7 brne .-46 ; 0x108
{
#if defined(TCCR1A) && defined(COM1A1)
case TIMER1A: cbi(TCCR1A, COM1A1); break;
#endif
#if defined(TCCR1A) && defined(COM1B1)
case TIMER1B: cbi(TCCR1A, COM1B1); break;
136: 20 91 80 00 lds r18, 0x0080
13a: 2f 7d andi r18, 0xDF ; 223
13c: 03 c0 rjmp .+6 ; 0x144
static void turnOffPWM(uint8_t timer)
{
switch (timer)
{
#if defined(TCCR1A) && defined(COM1A1)
case TIMER1A: cbi(TCCR1A, COM1A1); break;
13e: 20 91 80 00 lds r18, 0x0080
142: 2f 77 andi r18, 0x7F ; 127
#endif
#if defined(TCCR1A) && defined(COM1B1)
case TIMER1B: cbi(TCCR1A, COM1B1); break;
144: 20 93 80 00 sts 0x0080, r18
148: df cf rjmp .-66 ; 0x108
#if defined(TCCR2) && defined(COM21)
case TIMER2: cbi(TCCR2, COM21); break;
#endif

#if defined(TCCR0A) && defined(COM0A1)
case TIMER0A: cbi(TCCR0A, COM0A1); break;
14a: 24 b5 in r18, 0x24 ; 36
14c: 2f 77 andi r18, 0x7F ; 127
#endif

#if defined(TCCR0A) && defined(COM0B1)
case TIMER0B: cbi(TCCR0A, COM0B1); break;
14e: 24 bd out 0x24, r18 ; 36
150: db cf rjmp .-74 ; 0x108
152: 24 b5 in r18, 0x24 ; 36
154: 2f 7d andi r18, 0xDF ; 223
156: fb cf rjmp .-10 ; 0x14e
#endif
#if defined(TCCR2A) && defined(COM2A1)
case TIMER2A: cbi(TCCR2A, COM2A1); break;
158: 20 91 b0 00 lds r18, 0x00B0
15c: 2f 77 andi r18, 0x7F ; 127
#endif
#if defined(TCCR2A) && defined(COM2B1)
case TIMER2B: cbi(TCCR2A, COM2B1); break;
15e: 20 93 b0 00 sts 0x00B0, r18
162: d2 cf rjmp .-92 ; 0x108
164: 20 91 b0 00 lds r18, 0x00B0
168: 2f 7d andi r18, 0xDF ; 223
16a: f9 cf rjmp .-14 ; 0x15e
cli();

if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
16c: 9e 2b or r25, r30
16e: da cf rjmp .-76 ; 0x124

00000170 :
return m;
}

unsigned long micros() {
unsigned long m;
uint8_t oldSREG = SREG, t;
170: 3f b7 in r19, 0x3f ; 63

cli();
172: f8 94 cli
m = timer0_overflow_count;
174: 80 91 05 01 lds r24, 0x0105
178: 90 91 06 01 lds r25, 0x0106
17c: a0 91 07 01 lds r26, 0x0107
180: b0 91 08 01 lds r27, 0x0108
#if defined(TCNT0)
t = TCNT0;
184: 26 b5 in r18, 0x26 ; 38
#else
#error TIMER 0 not defined
#endif

#ifdef TIFR0
if ((TIFR0 & _BV(TOV0)) && (t < 255))
186: a8 9b sbis 0x15, 0 ; 21
188: 05 c0 rjmp .+10 ; 0x194
18a: 2f 3f cpi r18, 0xFF ; 255
18c: 19 f0 breq .+6 ; 0x194
m++;
18e: 01 96 adiw r24, 0x01 ; 1
190: a1 1d adc r26, r1
192: b1 1d adc r27, r1
#else
if ((TIFR & _BV(TOV0)) && (t < 255))
m++;
#endif

SREG = oldSREG;
194: 3f bf out 0x3f, r19 ; 63

return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
196: ba 2f mov r27, r26
198: a9 2f mov r26, r25
19a: 98 2f mov r25, r24
19c: 88 27 eor r24, r24
19e: bc 01 movw r22, r24
1a0: cd 01 movw r24, r26
1a2: 62 0f add r22, r18
1a4: 71 1d adc r23, r1
1a6: 81 1d adc r24, r1
1a8: 91 1d adc r25, r1
1aa: 42 e0 ldi r20, 0x02 ; 2
1ac: 66 0f add r22, r22
1ae: 77 1f adc r23, r23
1b0: 88 1f adc r24, r24
1b2: 99 1f adc r25, r25
1b4: 4a 95 dec r20
1b6: d1 f7 brne .-12 ; 0x1ac
}
1b8: 08 95 ret

000001ba :

void delay(unsigned long ms)
1ba: 8f 92 push r8
1bc: 9f 92 push r9
1be: af 92 push r10
1c0: bf 92 push r11
1c2: cf 92 push r12
1c4: df 92 push r13
1c6: ef 92 push r14
1c8: ff 92 push r15
{
uint32_t start = micros();
1ca: 0e 94 b8 00 call 0x170 ; 0x170
1ce: 4b 01 movw r8, r22
1d0: 5c 01 movw r10, r24
1d2: 80 ed ldi r24, 0xD0 ; 208
1d4: c8 2e mov r12, r24
1d6: 87 e0 ldi r24, 0x07 ; 7
1d8: d8 2e mov r13, r24
1da: e1 2c mov r14, r1
1dc: f1 2c mov r15, r1

while (ms > 0) {
yield();
while ( ms > 0 && (micros() - start) >= 1000) {
1de: 0e 94 b8 00 call 0x170 ; 0x170
1e2: 68 19 sub r22, r8
1e4: 79 09 sbc r23, r9
1e6: 8a 09 sbc r24, r10
1e8: 9b 09 sbc r25, r11
1ea: 68 3e cpi r22, 0xE8 ; 232
1ec: 73 40 sbci r23, 0x03 ; 3
1ee: 81 05 cpc r24, r1
1f0: 91 05 cpc r25, r1
1f2: a8 f3 brcs .-22 ; 0x1de
ms--;
1f4: 21 e0 ldi r18, 0x01 ; 1
1f6: c2 1a sub r12, r18
1f8: d1 08 sbc r13, r1
1fa: e1 08 sbc r14, r1
1fc: f1 08 sbc r15, r1
start += 1000;
1fe: 88 ee ldi r24, 0xE8 ; 232
200: 88 0e add r8, r24
202: 83 e0 ldi r24, 0x03 ; 3
204: 98 1e adc r9, r24
206: a1 1c adc r10, r1
208: b1 1c adc r11, r1
{
uint32_t start = micros();

while (ms > 0) {
yield();
while ( ms > 0 && (micros() - start) >= 1000) {
20a: c1 14 cp r12, r1
20c: d1 04 cpc r13, r1
20e: e1 04 cpc r14, r1
210: f1 04 cpc r15, r1
212: 29 f7 brne .-54 ; 0x1de
ms--;
start += 1000;
}
}
}
214: ff 90 pop r15
216: ef 90 pop r14
218: df 90 pop r13
21a: cf 90 pop r12
21c: bf 90 pop r11
21e: af 90 pop r10
220: 9f 90 pop r9
222: 8f 90 pop r8
224: 08 95 ret

00000226 <__vector_16>:
#if defined(TIM0_OVF_vect)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
226: 1f 92 push r1
228: 0f 92 push r0
22a: 0f b6 in r0, 0x3f ; 63
22c: 0f 92 push r0
22e: 11 24 eor r1, r1
230: 2f 93 push r18
232: 3f 93 push r19
234: 8f 93 push r24
236: 9f 93 push r25
238: af 93 push r26
23a: bf 93 push r27
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
23c: 80 91 01 01 lds r24, 0x0101
240: 90 91 02 01 lds r25, 0x0102
244: a0 91 03 01 lds r26, 0x0103
248: b0 91 04 01 lds r27, 0x0104
unsigned char f = timer0_fract;
24c: 30 91 00 01 lds r19, 0x0100

m += MILLIS_INC;
f += FRACT_INC;
250: 23 e0 ldi r18, 0x03 ; 3
252: 23 0f add r18, r19
if (f >= FRACT_MAX) {
254: 2d 37 cpi r18, 0x7D ; 125
256: 58 f5 brcc .+86 ; 0x2ae <__vector_16+0x88>
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;

m += MILLIS_INC;
258: 01 96 adiw r24, 0x01 ; 1
25a: a1 1d adc r26, r1
25c: b1 1d adc r27, r1
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}

timer0_fract = f;
25e: 20 93 00 01 sts 0x0100, r18
timer0_millis = m;
262: 80 93 01 01 sts 0x0101, r24
266: 90 93 02 01 sts 0x0102, r25
26a: a0 93 03 01 sts 0x0103, r26
26e: b0 93 04 01 sts 0x0104, r27
timer0_overflow_count++;
272: 80 91 05 01 lds r24, 0x0105
276: 90 91 06 01 lds r25, 0x0106
27a: a0 91 07 01 lds r26, 0x0107
27e: b0 91 08 01 lds r27, 0x0108
282: 01 96 adiw r24, 0x01 ; 1
284: a1 1d adc r26, r1
286: b1 1d adc r27, r1
288: 80 93 05 01 sts 0x0105, r24
28c: 90 93 06 01 sts 0x0106, r25
290: a0 93 07 01 sts 0x0107, r26
294: b0 93 08 01 sts 0x0108, r27
}
298: bf 91 pop r27
29a: af 91 pop r26
29c: 9f 91 pop r25
29e: 8f 91 pop r24
2a0: 3f 91 pop r19
2a2: 2f 91 pop r18
2a4: 0f 90 pop r0
2a6: 0f be out 0x3f, r0 ; 63
2a8: 0f 90 pop r0
2aa: 1f 90 pop r1
2ac: 18 95 reti
unsigned char f = timer0_fract;

m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
2ae: 26 e8 ldi r18, 0x86 ; 134
2b0: 23 0f add r18, r19
m += 1;
2b2: 02 96 adiw r24, 0x02 ; 2
2b4: a1 1d adc r26, r1
2b6: b1 1d adc r27, r1
2b8: d2 cf rjmp .-92 ; 0x25e <__vector_16+0x38>

000002ba
:

void init()
{
// this needs to be called before setup() or some functions won't
// work there
sei();
2ba: 78 94 sei

// on the ATmega168, timer 0 is also used for fast hardware pwm
// (using phase-correct PWM would mean that timer 0 overflowed half as often
// resulting in different millis() behavior on the ATmega8 and ATmega168)
#if defined(TCCR0A) && defined(WGM01)
sbi(TCCR0A, WGM01);
2bc: 84 b5 in r24, 0x24 ; 36
2be: 82 60 ori r24, 0x02 ; 2
2c0: 84 bd out 0x24, r24 ; 36
sbi(TCCR0A, WGM00);
2c2: 84 b5 in r24, 0x24 ; 36
2c4: 81 60 ori r24, 0x01 ; 1
2c6: 84 bd out 0x24, r24 ; 36
// this combination is for the standard atmega8
sbi(TCCR0, CS01);
sbi(TCCR0, CS00);
#elif defined(TCCR0B) && defined(CS01) && defined(CS00)
// this combination is for the standard 168/328/1280/2560
sbi(TCCR0B, CS01);
2c8: 85 b5 in r24, 0x25 ; 37
2ca: 82 60 ori r24, 0x02 ; 2
2cc: 85 bd out 0x25, r24 ; 37
sbi(TCCR0B, CS00);
2ce: 85 b5 in r24, 0x25 ; 37
2d0: 81 60 ori r24, 0x01 ; 1
2d2: 85 bd out 0x25, r24 ; 37

// enable timer 0 overflow interrupt
#if defined(TIMSK) && defined(TOIE0)
sbi(TIMSK, TOIE0);
#elif defined(TIMSK0) && defined(TOIE0)
sbi(TIMSK0, TOIE0);
2d4: 80 91 6e 00 lds r24, 0x006E
2d8: 81 60 ori r24, 0x01 ; 1
2da: 80 93 6e 00 sts 0x006E, r24
// this is better for motors as it ensures an even waveform
// note, however, that fast pwm mode can achieve a frequency of up
// 8 MHz (with a 16 MHz clock) at 50% duty cycle

#if defined(TCCR1B) && defined(CS11) && defined(CS10)
TCCR1B = 0;
2de: 10 92 81 00 sts 0x0081, r1

// set timer 1 prescale factor to 64
sbi(TCCR1B, CS11);
2e2: 80 91 81 00 lds r24, 0x0081
2e6: 82 60 ori r24, 0x02 ; 2
2e8: 80 93 81 00 sts 0x0081, r24
#if F_CPU >= 8000000L
sbi(TCCR1B, CS10);
2ec: 80 91 81 00 lds r24, 0x0081
2f0: 81 60 ori r24, 0x01 ; 1
2f2: 80 93 81 00 sts 0x0081, r24
sbi(TCCR1, CS10);
#endif
#endif
// put timer 1 in 8-bit phase correct pwm mode
#if defined(TCCR1A) && defined(WGM10)
sbi(TCCR1A, WGM10);
2f6: 80 91 80 00 lds r24, 0x0080
2fa: 81 60 ori r24, 0x01 ; 1
2fc: 80 93 80 00 sts 0x0080, r24

// set timer 2 prescale factor to 64
#if defined(TCCR2) && defined(CS22)
sbi(TCCR2, CS22);
#elif defined(TCCR2B) && defined(CS22)
sbi(TCCR2B, CS22);
300: 80 91 b1 00 lds r24, 0x00B1
304: 84 60 ori r24, 0x04 ; 4
306: 80 93 b1 00 sts 0x00B1, r24

// configure timer 2 for phase correct pwm (8-bit)
#if defined(TCCR2) && defined(WGM20)
sbi(TCCR2, WGM20);
#elif defined(TCCR2A) && defined(WGM20)
sbi(TCCR2A, WGM20);
30a: 80 91 b0 00 lds r24, 0x00B0
30e: 81 60 ori r24, 0x01 ; 1
310: 80 93 b0 00 sts 0x00B0, r24
#endif

#if defined(ADCSRA)
// set a2d prescaler so we are inside the desired 50-200 KHz range.
#if F_CPU >= 16000000 // 16 MHz / 128 = 125 KHz
sbi(ADCSRA, ADPS2);
314: 80 91 7a 00 lds r24, 0x007A
318: 84 60 ori r24, 0x04 ; 4
31a: 80 93 7a 00 sts 0x007A, r24
sbi(ADCSRA, ADPS1);
31e: 80 91 7a 00 lds r24, 0x007A
322: 82 60 ori r24, 0x02 ; 2
324: 80 93 7a 00 sts 0x007A, r24
sbi(ADCSRA, ADPS0);
328: 80 91 7a 00 lds r24, 0x007A
32c: 81 60 ori r24, 0x01 ; 1
32e: 80 93 7a 00 sts 0x007A, r24
cbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
#endif
// enable a2d conversions
sbi(ADCSRA, ADEN);
332: 80 91 7a 00 lds r24, 0x007A
336: 80 68 ori r24, 0x80 ; 128
338: 80 93 7a 00 sts 0x007A, r24
// here so they can be used as normal digital i/o; they will be
// reconnected in Serial.begin()
#if defined(UCSRB)
UCSRB = 0;
#elif defined(UCSR0B)
UCSR0B = 0;
33c: 10 92 c1 00 sts 0x00C1, r1
#include "wiring_private.h"
#include "pins_arduino.h"

void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin);
340: ed e9 ldi r30, 0x9D ; 157
342: f0 e0 ldi r31, 0x00 ; 0
344: 24 91 lpm r18, Z+
uint8_t port = digitalPinToPort(pin);
346: e9 e8 ldi r30, 0x89 ; 137
348: f0 e0 ldi r31, 0x00 ; 0
34a: 84 91 lpm r24, Z+
volatile uint8_t *reg, *out;

if (port == NOT_A_PIN) return;
34c: 88 23 and r24, r24
34e: 99 f0 breq .+38 ; 0x376

// JWS: can I let the optimizer do this?
reg = portModeRegister(port);
350: 90 e0 ldi r25, 0x00 ; 0
352: 88 0f add r24, r24
354: 99 1f adc r25, r25
356: fc 01 movw r30, r24
358: e8 59 subi r30, 0x98 ; 152
35a: ff 4f sbci r31, 0xFF ; 255
35c: a5 91 lpm r26, Z+
35e: b4 91 lpm r27, Z+
out = portOutputRegister(port);
360: fc 01 movw r30, r24
362: ee 58 subi r30, 0x8E ; 142
364: ff 4f sbci r31, 0xFF ; 255
366: 85 91 lpm r24, Z+
368: 94 91 lpm r25, Z+
cli();
*reg &= ~bit;
*out |= bit;
SREG = oldSREG;
} else {
uint8_t oldSREG = SREG;
36a: 8f b7 in r24, 0x3f ; 63
cli();
36c: f8 94 cli
*reg |= bit;
36e: ec 91 ld r30, X
370: e2 2b or r30, r18
372: ec 93 st X, r30
SREG = oldSREG;
374: 8f bf out 0x3f, r24 ; 63

setup();

for (;;) {
loop();
if (serialEventRun) serialEventRun();
376: c0 e0 ldi r28, 0x00 ; 0
378: d0 e0 ldi r29, 0x00 ; 0
pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
37a: 81 e0 ldi r24, 0x01 ; 1
37c: 0e 94 70 00 call 0xe0 ; 0xe0
delay(2000); // wait for a second
380: 0e 94 dd 00 call 0x1ba ; 0x1ba
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
384: 80 e0 ldi r24, 0x00 ; 0
386: 0e 94 70 00 call 0xe0 ; 0xe0
delay(2000); // wait for a second
38a: 0e 94 dd 00 call 0x1ba ; 0x1ba
38e: 20 97 sbiw r28, 0x00 ; 0
390: a1 f3 breq .-24 ; 0x37a
392: 0e 94 00 00 call 0 ; 0x0 <__vectors>
396: f1 cf rjmp .-30 ; 0x37a

00000398 <_exit>:
398: f8 94 cli

0000039a <__stop_program>:
39a: ff cf rjmp .-2 ; 0x39a <__stop_program>







2024.02.13 16:01 | pmlink.png 固定リンク | folder.png その他・雑談

- CafeLog -