The program and its instructions

The C-program that we will use is shown in Figure 5.

/* A simple C program */ 

/* include stdio for printout purposes */ 
#include <stdio.h>

/* main function */ 
int main(void)
    printf("Hello from a C program\n");
    return 0; 

Figure 5. A C-program for printing the string "Hello from a C program".

This the ARM view - other views are Intel-x86

The program in Figure 5 is supposed to be stored in a text file, named hello_c.c.

Using a C-compiler, instructions for the processor residing inside the computer can be generated. The compiler generates instructions for the particular processor used. In this book we will use a computer with a 32-bit ARM Cortex-A8 processor.

We will use the gcc compiler.

The following command can be used to compile the code in Figure 5:

arm-none-eabi-gcc -c -mcpu=cortex-a8 hello_c.c

The result of the compilation is an object file. We can inspect the format of this file by giving the command file hello_c.o. The result of giving this command is that a message informing about the type of the file is printed. The message starts with

hello_c.o: ELF 32-bit LSB relocatable, ARM, version 1 

which shows that the file is of type ELF.

We can generate assembly code. This is done using the same command as was done for the compilation above, but instead of using the command switch -c, the switch -S is used instead. The result of using this command is that assembly code is generated. An extract of the generated assembly code is shown in Figure 6.

	.section	.rodata
	.align	2
	.ascii	"Hello from a C program\000"
	.align	2
	.global	main
	.type	main, %function
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 1, uses_anonymous_args = 0
	stmfd	sp!, {fp, lr}
	add	fp, sp, #4
	movw	r0, #:lower16:.LC0
	movt	r0, #:upper16:.LC0
	bl	puts
	mov	r3, #0
	mov	r0, r3
	ldmfd	sp!, {fp, pc}

Figure 6. The generated assembly code, from a compilation of the program in Figure TBD

This the ARM view - other views are Intel-x86

We see different instructions in Figure 6. Here we describe the generated assembly code.

We show a selection of the generated assembly code. We see data and code. We see global main. It needs to be global since someone wants to call it! Who? The OS, or our startup code when we run it directly, with no OS.

Perhaps we also see some extern declarations, like printf, since it belongs to a library.

We see a label and the string to print. We see code, in the form of the main subroutine. We do not see relative adresses etc. Perhaps we need to do an objdump for that? So we ask ourselves

  • Which instructions can be used?
  • Which registers can be used?
  • Are some registers more special than others? Or, do registers have dedicated tasks associated with them? Yes, some of them have.