Unlike a Windows C/C++ Hello World tutorial, we will not be printing output to the console. Instead we will connect an LED to an input/output pin on the microcontroller and create a simple assembly program to turn the LED on.I will try to avoid making real schematics until it becomes really necessary, so here is a picture of the setup:GND — 1KOhm — LED — (20)

With the hardware done, it’s time to move on to the software.

Open MPLAB

Select Project/Project Wizard… Click Next

Select your microcontroller (PIC18F4550). Click Next

Choose Microchip MPASM Toolsuite. The locations should already be set up, but in case they aren’t, you can find the files in :\Program Files\Microchip\MPASM Suite\. Click Next

Click Browse… and select a directory and name for your project Tutorial2. For some reason, Microchip tools have some problem with long file paths, so you are limited to a maximum 62 character project path. A good directory might be :\pic\tutorial2 Click Next

Don’t add any files. Keep clicking Next, then click FinishYou should now see the project window titled Tutorial2.mcw. If you don’t, click View/Project. Similarly, click View/Output if you do not see the output window. Windows inside the IDE can be docked by right clicking the blue title bar, selecting Dockable and dragging the window to an edge of the IDE. Click File/New to open a new editor window. Rearrage your windows to your liking.

Mine looks like this:

Type

#include<18f4550>

at the top of the text file. Wow! Your first line of code. Better save! Click File/Save As…, find the project directory and save file as tutorial2.asm. Note: You need to make sure that the file saves with the .asm extension by typing it yourself.

To add the file into your project, right click Source Files and click Add Files…. Select tutorial2.asm and click Open.

It may also be helpful to add the include file into the project for reference. Right click Header Files and click Add Files…. Cruise to :\Program Files\Microchip\MPASM Suite and find the file P18F4550.INC.

Open the include file by double clicking on it. Note the comment (comments are marked by semicolons) toward the top:

; This header file defines configurations, registers, and other useful; bits of information for the PIC18F4550 microcontroller. These names
; are taken to match the data sheets as closely as possible.

Unfortunately, this means that you will have to become friends with the datasheet. Anytime you wish to use a peripheral, you need to consult the datasheet to find out which file registers perform the task you need. Then, confirm in the include file that the register names are consistent by searching for them.

Back to the tutorial2.asm..

Before any real coding gets done, the configuration bits (described in the datasheet – Section 25.1) must be set. These bits configure various aspects of the microcontroller’s operation that must be set before any code actually runs. Some recommend setting all of the configuration bits to make sure that everything is correct, but we will not be doing that at this point. Instead, we will set a few important bits that will allow our program to run:

The watchdog timer is a failsafe mechanism that resets the microcontroller in case there is a problem in the code. This may receive a tutorial later on. It’s mainly useful for commercial applications and will only be a hindrance in this tutorial. Therefore it will be turned off.

The MCLEAR pin (1) needs to be enabled to be able to use the debugging features (which we will be using shortly).

The DEBUG bit dedicates RB6 (39) and RB7 (40) to the debugger, instead of leaving them as I/O pins.

LVP will be disabled if you are programming with the PicKit 2 since it uses high voltage programming.

Last, but not least (the least least, actually) is the oscillator setup. We will use the internal oscillator. This means that the clock signal for the microcontroller will be generated inside the PIC. However, the default setting is an external oscillator (meaning that it will expect a clock signal on one of the pins), meaning that this must be set, or this tutorial will not work.

org 0; start code at 0

According to the MPASM Help (referenced above), the org directive allows the user to :
Set the program origin for subsequent code at the address defined in expr (0 in this case). If no org is specified, code generation will begin at address zero.For PIC18 devices, only even-numbered expr values are allowed.
This means that org dictates where in the microcontroller’s memory to place the data following it. Even though the default behavior is to start the code at memory location 0, it is a good idea to have this directive to mark the start of the code.

Now, the real code begins. A brief explanation of what this program does might help make the code easier to understand. First, the variables are declared and set to 0. Then, a pin is set up to output a value to turn the LED on and off. We will be using PORT D, PIN 1 (20). Note that this is the second pin on PORT D (after pin 0). I chose this port/pin for two reasons. First, it is at the end of the chip, making it easy to access. Second, PORT D is the only port that does not have some non-digital-I/O action using some of its pins by default, making it easiest to set up. Once the port is set up correctly, PIN 1 (20) is toggled. Then, a delay is necessary as the PIC runs at a default speed of 1Mhz (blinking far too fast to see). After the delay loop, the code goes back and toggles the pin. This cycle continues indefinitely.

The res directive reserves memory for variables.
This is a good time to mention that there are 3 types of “words” that you can use in assembler:
Directives/Instructions (blue): Must be preceeded with a tab or space
Labels (purple): Variable names are considered labels. Should start at the beginning of a line
Literals (black): Numbers and strings are literals, meaning that they do not have symbolic meaning other than the number/letter sequence they represent. These usually follow some instruction

Start:
CLRF PORTD
CLRF TRISD
CLRF Delay1
CLRF Delay2

The label Start, followed by a colon represents a point in the code that can be returned to using the goto/call instructions. A goto instruction simply moves program flow to a specified address or label. The call instruction will be covered later, but it performs a similar action to calling a C function (which returns to the same point once it is finished).PORT D can be accessed in two different ways. The PORTD register allows the port values to be written. However, it may be useful to read back an output value set on a certain pin. A latch attached to each PORT D pin allows this value to be stored. LATD is the register that allows access to the pin latches. A write to PORTD and LATD has the same result. Only a LATD read, however, will provide the correct output value of a pin. CLRF is an instruction that clears the file register (F) supplied. In this case, the PORTD register is cleared. According to the datasheet, this initializes PORTD by clearing the data latches. Next, the data direction must be set. PORTD pins can function either as digital inputs or digital outputs. In this case we want outputs, to control the LED. The register TRISD controls the direction of the port. A good way to remember how to set the direction is that in TRISD 0s are Outputs and 1s are Inputs. Therefore, we clear TRISD to set the whole port to output. Note: TRISD bits control the same pins as the PORTD bits. For example, PORT D PIN 1 is set to input or output by the second bit in TRISD and written to by the second bit in PORTD.
The Delay variables are also set to 0.

(The delay algorithm has been taken from the example code in the MicroChip 16F 44-Pin Demo Board User Guide). The decfsz instruction subtracts the requested amount (second argument) from the file register (F) provided (first argument) and then checks the value of that register. If it is 0, the following instruction is ignored. This delay loop is actually a nested loop. Since Delay1 was 0 at the start, decrementing 1 from this 8 bit register turns it into 255. The goto instruction then moves the program flow back to the decfsz instruction. This continues until Delay1 reaches 1. When decfsz runs again, Delay1 becomes 0. As promised, the following goto instruction is skipped so the second decfsz instruction is run, subtracting 1 from Delay 2. Delay 2 was also 0 and becomes 255. The following goto instruction brings it back to the FIRST decfsz instruction, causing Delay1 to be decremented another 255 times before decrementing another 1 from Delay2. To quantify the delay, a reference from the MicroChip 16F 44-Pin Demo Board User Guide: Each loop takes 3 instruction times; one for the decrement and two for the GOTO and the counter will force it to go around 256 times, which takes it a total of 768 instruction times (768 µs) to execute. The inner loop (Delay1) takes 768 µs plus 3 for the outer loop(Delay2), but now it’s executed another 256 times, (768 + 3) * 256 = 197376 µs = 0.197s.

Once the delay code is finished (the second goto is skipped because Delay2 turns to 0), the goto MainLoop instruction is executed and the cycle begins again. The end directive is also present, as it must be in every assembly program. However, it should never be reached.

The program is now complete. Click Project/Build All to build it. You should see BUILD SUCCEEDED in the build tab in the output window. Then, click Programmer/Select Programmer and choose PicKit2. You should see

There are currently 39 responses to “Tutorial 2 – “Hello World” Program in Assembly Language”

Yeah! Thanks for this tutorial! I just got my first program working with an 18f4553 and a pickit2! With the help of a electronics shop, I had to to put together my own 6 pin connector for the pickit2 also.

Hmmm. It seems I may have spoken too soon. I think I had a bug in my initial program that allowed me to get the results I was expecting (the flashing LED). When I now use the program as you have posted, I don’t get a flashing LED. Some debugging shows that when I comment out both Delay loops, I get a voltage out of pin 20 of 1.3V. With just the Delay2 loop commented out, I get a voltage on pin 20 of 1.6V. With both loops in place, I get a voltage output on pin 20 of 2.5V. But no flashing in any of these cases. It seems I’ve managed to do some kind of odd Pulse Width Modulation. I’m not sure why the voltage of pin 20 is growing larger with increasing delay though. The clock rate of my PIC 18f4553 seems to be 48 MHz. Perhaps that’s a faster clock rate on the PIC you were using originally? Any thoughts would be appreciated.

Ok. Finally, I think I’ve figured out where my problems were. I’m working with the PIC 18f4553 and I was getting flaky operation of the LED in this circuit. It would work for a while, then not work. At most, though the LED would flash a dozen times. After pretty much replacing each component of the circuit (PIC, breadboard, wires etc), I narrowed the problem down to the MCLR pin (pin 1). It seems static electricity was generating enough electrical variation to cause a MCLR signal. Actually, that pin needs to be high (I think), so perhaps this isn’t that unusual. I am running the programmed PIC with the programmer disconnected, so I’m not sure if that’s a factor here. I now have the MCLR pin tied to +5v. All is well!! (Also, I don’t think this has any immediate bearing on the problem I was having, but I have placed a pair of 0.1 microfarad capacators on the Vdd lines. I’m reading a book by Myke Predko “Programming and Customizing the PIC Microcontroller — 3rd Ed” and this was recommended. Myke you didn’t proof check the code figures in that book– they have line wrap!!).

Mostafa,
I hope to find some free time in the near future to finish a few more simple assembly tutorials and move to C. This website was originally a way for me to start documenting my work with the 18F4550, but turned into a series of tutorials because I was unable to find any reliable sources of assembly tutorials for these microcontrollers. Please do check back in the future..

Also, if you have any specific questions, feel free to ask them in the forum

You did not set BSR to 0x0f ? And it still works ? IMHO after RESET, BSR = 0x00. And all special registers like PORTD, TRISD etc. are on page 15. Can you explain it for me ? I programmed only 16F processors and they are a little bit different…

I would like to note that the data space reservation at the beginning of your program test2.asm is wrong. The MPASM compiler says: “No memory has been reserved by this instruction”. This will result in an infinite loop (instead of a finite delay) and the LED will not blink.

[…] the basics of PIC18F C programming and provide simple sample code for a blinking LED, similar to tutorial 2. If I receive positive feedback, more tutorials will follow. This tutorial assumes minimal […]

This is such an awesome tutorial. I have programmed PIC16s and am now learning the PIC18. I needed a quick start for testing my setup to see how things are working. The ability to toggle an LED allows me to gauge how the oscillator is working by the output switching and giving me a value my freq counter can read.

Really neat tutorial. You should really make pages like this using the actual code in your project. If you write the program as you have here, it WILL NOT work. It needs minor modifications, but never the less, it doesn’t work. As they say, “Close, but no cigar.” Anyhow, thanks for the page and site, its pretty useful for a beginner.

Thanks for the great tutorial, Andrey!
I’m just getting started with PIC controllers and I don’t think I would have been able to find a better “Getting-started” tutorial. This has really helped my frustration level go WAYYYY down.

sir in the above given code an error due to BTG is occurring, the error goes like this ” Operand contains unresolvable labels or is too complex ” instead of using this instruction is there any other instruction(group of instructions) to do the same operation…

Hi, very good tut I am new to pic micocontrollers but do program in Vb6/.Vb.net/C#(beginner level) as I find this stuff interesting. Once I get up to scratch with
the pic stuff I would like to interface a .net app to the picf4550 through usb, I have read that the picf4550 is a usb client device.

Thanks a lot for the tutorial it is awsome! I just got a problem with the implementation of the “RES” directive… When I built the project a problem came out: “RES directive cannot reserve odd number of bytes in PIC18 absolute mode” and i found out a solution but I didn’t understand quite well..
“…the compiler ask for “Absolute” or “Reloctable” code. Ok, I didn’t read the manual, so I choosed “Relocatable”. There was a line like “delay res 1” in the code and the compiler said “No memory has been reserved by this instruction”. After changing to “Absolute”, the compiler said “RES directive cannot reserve odd number of bytes in PIC18 absolute mode”…”
Can somebody tell my why happened this? I just change the 1 for a 2 and it compiled but why?
Thanks a lot again!