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 Intel-x86 view - other views are ARM

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 Intel x86 processor.

We will use the gcc compiler.

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

gcc -m32 -c 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, Intel 80386, 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
.LC0:
	.string	"Hello from a C program"
	.text
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	andl	$-16, %esp
	subl	$16, %esp
	movl	$.LC0, (%esp)
	call	puts
	movl	$0, %eax
	leave
	ret

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

This the Intel-x86 view - other views are ARM

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.

  • Intel-x86
  • ARM