Arduino - Programming in Assembly                                                         Home : www.sharetechnote.com

 

 

 

 

Programming in Assembly

 

 

 

Compile and Uploading with Command Window

 

Step 1 : Go to the directory where you put the Assembly source code

 

First go to the directory where the Assembly Code is located (I created a Assmebly name as Blink.S). The content of the directory is as shown below.

 

C:\Arduino\asm\Blink>dir

 Volume in drive C is Windows

 Volume Serial Number is F8D3-F022

 

 Directory of C:\Arduino\asm\Blink

 

07/27/2016  06:09 PM    <DIR>          .

07/27/2016  06:09 PM    <DIR>          ..

07/27/2016  05:25 PM               252 blink.S

               1 File(s)            252 bytes

               2 Dir(s)  65,290,346,496 bytes free

 

 

Step 2 : Comple the source code

 

Next step is to compile the assembly code. The complier program is avr-as. Since the location of the folder containing the avr-as is not added in the Windows PATH variable, you need to specify the full Path of the program as shown below.

 

C:\Arduino\C\Blink>"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-as" -g -mmcu=atmega328p -o Blink.o Blink.S

 

NOTE 1 : The location of the compiler might be different depending on Arduino IDE version and installation directly. So before you try this and find out exact location of the folder. In Windows, you may use Windows File Explorer and search avr-as. In Linux, you may try 'ls -al -R | grep "avr-as"'

 

After the compliation is complete, check the contents of the folder again and you will notice that following file is created.

 

C:\Arduino\asm\Blink>dir

 Volume in drive C is Windows

 Volume Serial Number is F8D3-F022

 

 Directory of C:\Arduino\asm\Blink

 

07/27/2016  06:12 PM    <DIR>          .

07/27/2016  06:12 PM    <DIR>          ..

07/27/2016  06:12 PM             1,300 Blink.o

07/27/2016  05:25 PM               252 blink.S

               2 File(s)          1,552 bytes

               2 Dir(s)  65,289,904,128 bytes free

 

 

Step 3 : Link the object code

 

Now link the object file as shown below.

 

C:\Arduino\asm\Blink>"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-ld" -o Blink Blink.o

 

Now you have a new file created as shown below.

 

C:\Arduino\asm\Blink>dir

 Volume in drive C is Windows

 Volume Serial Number is F8D3-F022

 

 Directory of C:\Arduino\C\Blink

 

07/27/2016  06:14 PM    <DIR>          .

07/27/2016  06:14 PM    <DIR>          ..

07/27/2016  06:14 PM             1,379 Blink

07/27/2016  06:12 PM             1,300 Blink.o

07/27/2016  05:25 PM               252 blink.S

               3 File(s)          2,931 bytes

               2 Dir(s)  65,289,900,032 bytes free

 

 

Step 4 : Convert the linked file into .hex format

 

Now you convert the linked file into a binary file that can be directly loaded to the EEPROM of the Arduino board as shown below.

 

C:\Arduino\asm\Blink>"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-objcopy" -O ihex -R .eeprom Blink Blink.hex

 

Now you see the new file in hex format created as shown below.

 

C:\Arduino\asm\Blink>dir

 Volume in drive C is Windows

 Volume Serial Number is F8D3-F022

 

 Directory of C:\Arduino\asm\Blink

 

07/27/2016  06:16 PM    <DIR>          .

07/27/2016  06:16 PM    <DIR>          ..

07/27/2016  06:14 PM             1,379 Blink

07/27/2016  06:16 PM                50 Blink.hex

07/27/2016  06:12 PM             1,300 Blink.o

07/27/2016  05:25 PM               252 blink.S

               4 File(s)          2,981 bytes

               2 Dir(s)  65,290,428,416 bytes free

 

 

Step 5 : Upload the hex file into Arduino board

 

Now the last step is to upload the hex file onto the board and this was the step that gave me a lot of trouble and it took me long time for me to find the solution to make this work.  The problem at the beginning turned out to be because I missed out the option  -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" . So don't forget to specify this option. Also keep in mind that the location of the file avrdude.conf may be different in your environement. Find the exact location of this file first before you try this command.  If you are really motivated, open up this file and try to decipher the meaning of the all the information in the file.

 

C:\Arduino\asm\Blink>"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude" -C "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" -F -V -c arduino -p ATMEGA328P -P COM3 -b 115200 -U flash:w:Blink.hex

 

NOTE : I am using Arduino UNO R3 and my Arduino board is connected to my Windows PC via COM3 port. If you are using different type of Arduino board and connection is through different COM3 port, you may need to change the variable for -p and -P option in the command above.

 

If all the options typed in the command line is correct, you will get the print outs as shown below, otherwise you may get some error message. Once you get the print out as shown below, you will see the program running on the board. (In this example, Blink.c has the code blinking the onboard LED connected to PIN 13 on Arduino Uno).

 

avrdude: AVR device initialized and ready to accept instructions

 

Reading | ################################################## | 100% 0.01s

 

avrdude: Device signature = 0x1e950f

avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed

         To disable this feature, specify the -D option.

avrdude: erasing chip

avrdude: reading input file "Blink.hex"

avrdude: input file Blink.hex auto detected as Intel Hex

avrdude: writing flash (12 bytes):

 

Writing | ################################################## | 100% 0.02s

 

avrdude: 12 bytes of flash written

 

avrdude: safemode: Fuses OK (H:00, E:00, L:00)

 

avrdude done.  Thank you.

 

 

Convert o (Object File) into Assembly Code

 

Step 1 : Create an Arduino Sketch file as shown in the following example

 

void setup() {

  Serial.begin(9600);

  Serial.println("Hello World !");

 

}

 

void loop() {

}

 

 

Step 2 :  Go to the folder where *.elf file is located and confirm that you have an elf file in the folder. (If you don't know how to find this location, refer to the section Compile and upload in verbose mode)

 

C:\Users\Sharetechnote\AppData\Local\Temp\buildbb526efb0f6c38750b56f64014c17ca2.tmp\sketch>dir

...

 

01/28/2017  12:21 AM    <DIR>          .

01/28/2017  12:21 AM    <DIR>          ..

01/28/2017  12:21 AM               633 Serial_01.ino.cpp

01/28/2017  12:21 AM             1,134 Serial_01.ino.cpp.d

01/28/2017  12:21 AM             5,412 Serial_01.ino.cpp.o

 

 

Step 3 :  Run following command. Then the generated assmebly file will be stored in Serial_01.txt file.

 

C:\Users\Sharetechnote\AppData\Local\Temp\buildbb526efb0f6c38750b56f64014c17ca2.tmp\sketch>"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-objdump" -D -S Serial_01.ino.cpp.o > Serial_01.txt

 

Note : Try without '-D' option and see what the difference is

 

 

Convert elf into Assembly Code / Extract Assembly Code from elf

 

Step 1 : Create an Arduino Sketch file as shown in the following example

 

void setup() {

  Serial.begin(9600);

  Serial.println("Hello World !");

 

}

 

void loop() {

}

 

 

Step 2 :  Go to the folder where *.elf file is located and confirm that you have an elf file in the folder. (If you don't know how to find this location, refer to the section Compile and upload in verbose mode)

 

C:\Users\Sharetechnote\AppData\Local\Temp\buildbb526efb0f6c38750b56f64014c17ca2.tmp>dir

...

 

01/28/2017  12:32 AM    <DIR>          .

01/28/2017  12:32 AM    <DIR>          ..

01/28/2017  12:21 AM               569 build.options.json

01/28/2017  12:21 AM    <DIR>          core

01/28/2017  12:21 AM    <DIR>          libraries

01/28/2017  12:21 AM    <DIR>          preproc

01/28/2017  12:21 AM                13 Serial_01.ino.eep

01/28/2017  12:21 AM            61,256 Serial_01.ino.elf

01/28/2017  12:21 AM             5,082 Serial_01.ino.hex

01/28/2017  12:21 AM             6,388 Serial_01.ino.with_bootloader.hex

 

 

Step 3 :  Run following command. Then the generated assmebly file will be stored in Serial_01.txt file.

 

C:\Users\CA090406\AppData\Local\Temp\buildbb526efb0f6c38750b56f64014c17ca2.tmp>"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-objdump" -d Serial_01.ino.elf > Serial_01.txt

 

C:\Users\Sharetechnote\AppData\Local\Temp\buildbb526efb0f6c38750b56f64014c17ca2.tmp>dir

...

 

01/28/2017  12:32 AM    <DIR>          .

01/28/2017  12:32 AM    <DIR>          ..

01/28/2017  12:21 AM               569 build.options.json

01/28/2017  12:21 AM    <DIR>          core

01/28/2017  12:21 AM    <DIR>          libraries

01/28/2017  12:21 AM    <DIR>          preproc

01/28/2017  12:21 AM                13 Serial_01.ino.eep

01/28/2017  12:21 AM            61,256 Serial_01.ino.elf

01/28/2017  12:21 AM             5,082 Serial_01.ino.hex

01/28/2017  12:21 AM             6,388 Serial_01.ino.with_bootloader.hex

01/28/2017  12:32 AM            30,333 Serial_01.txt  // Click here to get this file

 

 

Examples

 

<  Blink > ===============================================================

 

;  turns on an LED which is connected to PB5 (digital out 13)

 

 

.equ    PORTB, 0x05

.equ    DDRB, 0x04

 

.org 0x0000

    jmp main

 

main:

    ldi r16,0b00100000

    out DDRB, r16

    out PORTB, r16

 

Start:

    rjmp Start

 

 

Pointer Register

 

When you read Arduino Assembly code or AVR technical document, you would see a lot of examples using the character X, Y, Z.  These characters are special characters used to implement Pointers. Each of these characters indicates a specific registers as listed below.

 

X = R26:R27

Y = R28:R29

Z = R30:R31

 

 

Instruction Set

 

 

CBI (Clear Bit in I/O Register)

 

Syntax : CBI <P>,<b>  // Set the bit <b> in the port <P> to be '0'

Example :

 

 

LDD (Load Indirect with Displacement)

 

Syntax : LDD <Register>,<Y+d>  // RegisterD <- the value stored at the address (Y+d)

Example : ldd r30, Y+16    // r30 <- the value stored at the address (Y+16)

 

 

LDI (Load Immediate)

 

Syntax : LDI <Register>,<Constant Value>  // Register <- ConstantValue

Example : ldi r18, 0x06    // Store the value 0x16 into the register R18

 

 

MOVW (Move Word)

 

Syntax : MOVW <RegisterD>,<RegisterS>  // RegisterD <- RegisterS, 1+RegisterD <- 1+RegisterS

Example : movw    r28, r24    // r28 <- r24, r29 <- r25

 

 

SBI (Set Bit in I/O Register)

 

Syntax : SBI <P>,<b>  // Set the bit <b> in the port <P> to be '1'

Example :

 

 

ST (Store Indiret)

 

Syntax : ST Z,<Register>  // (Z) <- Register

Example : st  Z, r24    // (Z) <- r24

 

 

Reference :

 

[1] Native Assembler Programming on Arduino