The assembler processes your source code into a form that can be inserted at given location in main memory for execution by the processor. The assembler creates a “relocatable object file” from your source code - that is, it replaces the mnemonics in your source file with their machine code counterparts, and then writes the list of machine codes to a file that can be placed anywhere in the ARM memory map. Another program called the linker combines your program’s object file with any other needed system files (or other object files), resolves any shared resources (like data locations), and creates one file that can be placed in memory for execution. A simple loader program copies the unified object file produced by the linker to a predetermined memory location, sets a pointer to the first instruction ofthat file, and then enables the processor to execute that first instruction. From there, the processor keeps executing your program until it halts due to an error, or due to encountering a “breakpoint”. (Breakpoints are exceptions which cause the processor to halt normal operations and execute special/protected instructions - more on this topic in the next project).
Most assemblers are so-called “two pass” assemblers, because they read the source file twice. On the first pass, the assembler pays attention to labels, symbols, and directives, and builds the “symbol table”. The symbol table creates a memory map that associates data items, labels, and symbols with particular memory addresses. The second pass converts the assembly instructions into machine codes, and uses the symbol table as needed to create numerical values (addresses) for labels used for branch addresses, data items, and other items.
Assembly Source Files
An assembly source file contains labels, comments, directives, and instructions. Labels are used in the source file to identify locations of instructions, data, and blocks of code. The assembler associates labels with memory addresses, and those addresses can be used by the executing program to locate data or blocks of code. All assembly programs start with a “main:” label to identify the address of the first instruction. The linker uses this label to “link” your source file with other system files as needed. All labels are text strings ending with a colon.
Directives are used to define symbols (or constants), define data storage areas, and to control the behavior of the assembler. In the Xilinx SDK tool, directives begin with a period followed by any one of several dozen predefined text strings. Every Assembler uses directives, but there are no standards for directives, so every Assembler tool will have its own collection of directives, and its own syntax for using them.
SDK includes many Assembler directives, but only a few are commonly used. In our first program, we will use the “.text”, “.global”, “.set”, and “.end” directives. The text directive identifies the section of the source file that contains executable code – it is always required. The global directive is used to identify the label that is associated with the first executable instruction – we will generally use “.global main”, and the label “main:”, to identify the first instruction. The set directive allows symbols to be associated with numerical values (just like constants in other languages), to make the code more readable, and certain parameters easier to modify. The end directive tells the assembler where to stop the assembly process – everything after the end directive is ignored.
We will encounter a few more directives in later design projects.
Assembly program structure
Assembly programs in Xilinx’s SDK all have a common format. The first line must be “.text”. This directive defines the source file section that contains executable instructions.
The next line must be “.global main”. This directive makes the label “main” visible to other tools in the tool chain (for example, the linker). Then, the first line of your assembly code must have the label “main:”.
If you use constants, you can use the directive “.set” to define them in the next few lines.
After the label “main” come the assembly instructions, including comments (//) and labels. At the end of your program, the “.end” directive informs the assembler there are no more instructions or directives.
.text .global main .set LED_BASEADDR, 0x4BB00000 main: /*Your code goes here*/ .end