c from hello world to 010101

53
By : BELLAJ BADR Fouder of Raspberry pi Moroccan community C language From hello world to 010101

Upload: bellaj-badr

Post on 17-Aug-2015

75 views

Category:

Software


0 download

TRANSCRIPT

Page 1: C from hello world to 010101

By : BELLAJ BADR

Fouder of Raspberry pi Moroccan community

C languageFrom hello world to 010101

Page 2: C from hello world to 010101

*C in Raspberry Pi

*How a C program is executed

*Hellow world in assembly

*Build your own OS « Hello world OS »

*C introduction

Page 3: C from hello world to 010101

*C introduction

Page 4: C from hello world to 010101

*C History* in 1971-73 Dennis M. Ritchie turned the B language into the C language, keeping most of the language B syntax while adding data-types and many other changes

Page 5: C from hello world to 010101

*Hello World

the most famous example program from the book is its "hello, world" program, which just prints out the text "hello, world" to the terminal, as an illustration of a minimal working C program. Numerous texts since then have followed that convention for introducing a programming language.

*in 1978 the publication of ”The C Programming Language” by Kernighan & Ritchie caused a revolution in the computing world.

Page 6: C from hello world to 010101

*first C program

#include <stdio.h>

int main(void) printf("My first C program\n"); return 0;

Page 7: C from hello world to 010101

*C is it !!

*Compiled language

*Interpreted language

*P-code language

Page 8: C from hello world to 010101

*Compile and Runon the Raspberry

pi

*gcc hello.c

=>your code has been compiled into a separate executable file which by default is named as a.out

*To execute program first, enter: ./first

Page 9: C from hello world to 010101

*Execution & compilation

process

*The compilation is performed in four sequential phases by the compilation system (a collection of four programs preprocessor,compiler, assembler, and linker).

* we could use the commands as (assembler), ld (link loader), and gdb (GNU debugger) from GCC(GNU Compiler Collection) .

*C code=> assembly code=>object file=>executable

Page 10: C from hello world to 010101

*What’s Happend?

Page 11: C from hello world to 010101
Page 12: C from hello world to 010101
Page 13: C from hello world to 010101

Assembly code

*To get the assembly code from our C code we use the « Gcc –s » command :

123

# gcc -S hello.c -o hello.s# cat hello.s

Page 14: C from hello world to 010101
Page 15: C from hello world to 010101

*Object code

123

# gcc -c hello.s -o hello.o# file hello.ohello.o: ELF 32-bit ,,,,,,,,,,,,

128# readelf -a hello.o

We can see that the hello.o is the object file that is actually an ELF 32-bit executable, which is not linked yet. If we want to run the executable, it will fail as noted below:

We can read the contents of the object file with the readelf program as follows

Page 16: C from hello world to 010101

*Linker & Excutable

*# chmod +x hello.o

*# ./hello.o

*bash: ./hello.o: cannot execute binary file => we need to link it

Page 17: C from hello world to 010101

*From object to excutable?

Page 18: C from hello world to 010101

*Elf file

*Generic ELF File Layout : A simple Executable ARM ELF file has the conceptual layout shown in the diagram on the right.

Page 19: C from hello world to 010101

*Cross compilations

we want to build object code for the ARM processor at the heart of the Raspberry Pi, we need a cross-compiler and its associated tools, which is usually called a "toolchain". Here we are using "crosstool-ng" to build such tool chain.

arm - non e - eabi - gcc

Page 20: C from hello world to 010101

*To understand the C compilation let’s look at the ARM assembly language

Page 21: C from hello world to 010101

*Hellow World in assembly

In this lab, you will learn to write ARM assembly language programs and test them on a Raspberry Pi, featuring the BCM2835 microprocessor

Rpi < 2 only support armv6 instructions While RPI 2 support armv7 instructions

Page 22: C from hello world to 010101

*all ARM instructions are 32 bits long. Here is a typical one:

*10101011100101010010100111101011

*Fortunately, we don't have to write ARM programs using such codes. Instead we use assembly language

Page 23: C from hello world to 010101

http://goo.gl/EVrLl0

Page 24: C from hello world to 010101

Registre CPSR

Page 25: C from hello world to 010101

*17 registre 32bit(4Oct

et)

Registres particuliersr13 alias sp : stack pointer pointeur sur pile de donnees r14 alias lr : lr stands for link register and itis the address of the instruction following the instruction that called us(return) r15 alias pc : program counter contains the address of the next instruction going to be executed

When the ARM processor executes an instruction, two things may happen at the end of its execution. If the instruction does not modify pc (and most instructions do not), pc is just incremented by 4 (like if we did add pc,

pc, #4). Why 4? Because in ARM, instructions are 32bit wide, so there are 4 bytes between every instruction. If the instruction modifies pc then the new value for pc is used

Once the processor has fully executed an instruction then it uses the value in the pc as the address for the next instruction to execute,This process of changing the value of pc is called branching. In ARM this done using branch instructions.

Page 26: C from hello world to 010101

cpsr (for Current Program StatusRegister) keeps some values that can be read and updated when executing an instruction

cmp r1, r2 /* updates cpsr doing "r1 ‐ r2", but r1 and r2 are not modified */

EQ (equal) When Z is enabled (Z is 1)NEQ (not equal). When Z is disabled. (Z is 0)

[r1, +#12] => an offset of 12 (4 bytes * 3 itemsskipped).

Page 27: C from hello world to 010101

*Basic ARM instruction

*Exemple d'instruction : addition

ADD r0,r1,r2 @ r0<-r1+r2

ADD r0,r0,#4 @ r0<-r0+4

SUB,

*L'instruction de ''mouvement'' de donnee

MOV rd,<Oprnd2> @ rd <- Oprnd2

*load : Memory =>registre

*store : registre=>memory

*.INCLUDE "fichier.s"

Page 28: C from hello world to 010101

*Le format des instructions ARM est fixe :

*Une instruction fait 4 octets (32 bits)

Page 29: C from hello world to 010101

*Exemple de codage d'une instruction :

*MOV r5,#7 @ Instruction Assembleur

*0b11100011101000000101000000000111

*=0xE3A05007 ( code langage machine)

Page 30: C from hello world to 010101
Page 31: C from hello world to 010101

*Codage d'instruction:

condition

*MOV r5,#7

* Execution inconditionnelles : Always

->1110

* Puis specification de famille d'operation

*( Data-processing : MOV, ADD, CMP ...)

->111000

* Puis indicateur d'operande immediat (I)

->1110001

Page 32: C from hello world to 010101

*Codes d'opérations :

Opcode

Page 33: C from hello world to 010101

MOV r5,#7

* C'est une operation Move =>Opcode

*->11100011101

* Puis indicateur ''pas de mise a jour

*des codes conditions'' (pas de S en suffixe)

*->111000111010

* MOV : pas de 1er operande (Rn a 0)

*->1110001110100000

* Registre destination R5 (Rd code pour 5)

*->11100011101000000101

*Format immediat : constante 8 bits et rotation

*constante = 0b00000111(binaire)=7décimal

* Pas besoin de deplacer la constante 8 bits

*pour obtenir la valeur immediate (rotation 0)

*->111000111010000001010000

* Constante 8 bits

*->11100011101000000101000000000111

Page 34: C from hello world to 010101

*Result

*MOV r5,#7

*0b11100011101000000101000000000111

*=0xE3A05007

Page 35: C from hello world to 010101

.datamsg:.ascii "Hello, Piday!\n"len = . ‐ msg.text.globl _start_start:/* syscall write(int fd, const void *buf, size_t count) needs 3 argument*/mov %r0, $1 /* fd ‐> stdout standard output*/ldr %r1, =msg /* buf ‐> msg */ldr %r2, =len /* count ‐> len(msg) */mov %r7, $4 /* write is syscall #4 */swi $0 /* invoke syscall *//* syscall exit(int status) */mov %r0, $0 /* status ‐> 0 */mov %r7, $1 /* exit is syscall #1 */swi $0 /* invoke syscall */

The C function s, including the ISO C standard ones, are widely used by programs, and are regarded as if they were not only an implementation of something in the C language, but also de fact o part of the operating system interface.=> glibc

Making call using C libit is rather unusual to perform system calls directly.It is almost always preferable to call the C library instead.

*Hello

Piday

Page 36: C from hello world to 010101

*To terminate a program

*MOV R7, #1

*SVC 0 6 of 23

*The number 1 placed in Register 7 tells the operating system to terminate this program. The instruction “SVC 0” is the system call, that transfers the program execution to the operating system. If you place a different number in R7, the operating system will perform a difference service.

on ARM, the system call identifier is put in register R7, arguments are passed in R0R6 (respecting “EABI arrangement” where appropriate,i.e. 64bit arguments), and the kernel is called with the ‘SWI 0’ instruction.

Page 37: C from hello world to 010101

Now, coming to Raspberry Pi, which is a Broadcom SOC,BCM 2835,based on ARM Processor. Every System Call is Index in the System Call Table. The Index is an Integer value which is passed to the Register R7, in case Platform. The registers, R0, R1 and R2 are used to pass the arguments of the System Call. The instruction, SWI, now being used as SVC, which is a Supervisor Call, used to jump to the Privileged Mode, to invoke the Kernel. The embedded with SVC #num, is used to refer to the Handler.svc #0 Hence, as an example, say, we want to invoke a System Call to print "Hello World\n". The System Call Index 'Write' is #4. Thus, the code will be something like,

Page 38: C from hello world to 010101

*Syscall

In Linux ARM we can perform a system call by using the instruction swi. This instruction means software interruption and its sole purpose is to make a system call to the operating system.

Linux we will always use swi #0 to perform a system call.

No system call in Linux receivesmore than 7 arguments and the arguments are passed in registers r0 to r6. If the system call returns some value it will be returned in register r0.

Page 39: C from hello world to 010101

Hello world, the system call way

As a simple illustration of calling the operating system we will write the archetypical “Hello world” program using system calls. In this case we will call the function write. Write receives three parameters: a file descriptor where we will write some data, a pointer to the data that will be written and the size of such data. Of these three, the most obscure may be now the file descriptor. Without entering into much details, it is just a number that identifies a file assigned to the process. Processes usually start with three preassigned files: the standard input, with the number 0, the standard output, with the number 1, and the standard error, with the number 2. We will write our messages to the standard output, so we will use the file descriptor 1.

Page 40: C from hello world to 010101
Page 41: C from hello world to 010101

.arch armv6

.section .rodata

.align 2

.dataHelloWorldString:.ascii "Hello World\n".LC0:.text.align 2.global main.type main, %functionmain:mov r7, #4mov r0, #1ldr r1,=HelloWorldStringmov r2, #12svc #0@ Need to exit the programmov r7, #1mov r0, #0svc #0.L3:.align 3.L2:.size main, .main.ident "GCC: (Debian 4.6.314+rpi1) 4.6.3".section .note.GNUstack,"",%progbits

Compile and run , ./program

Now, check 'dmesg' using,#dmesg | tail

Page 42: C from hello world to 010101

Write assembly in .s fileAs ‐o hello.o hello.S (output object file from assembly file)Ld ‐s ‐o hello hello.o (output exeutable file)

gcc ‐o hello hello.o

*Linker: Finally, the linker ﴾ld/ld.exe ﴿ links the object code with the library code to produce an executable file « hello/hello.exe".

*> ld ‐o hello.exe hello.o ...libraries...

Page 43: C from hello world to 010101

*Extra

"ldd" Utility ‐ List Dynamic‐Link LibrariesThe utility "ldd" examines an executable and displays a list of the shared libraries that it needs. For example,> ldd hello.exentdll.dll => /cygdrive/c/Windows/SYSTEM32/ntdll.dll (0x77bd0000)kernel32.dll => /cygdrive/c/Windows/system32/kernel32.dll (0x77600000)KERNELBASE.dll => /cygdrive/c/Windows/system32/KERNELBASE.dll (0x75fa0000)

Page 44: C from hello world to 010101

Gdb Debugger>> gdb hello>> gdb start>> gdb disassemble

*Debugging :* as gstabs o filename.o filename.s =>get

assambly

* If you want to use gdb, you need to invoke the assembler with some additional options.

* When gdb starts, we need to set a breakpoint.

* The execution of the program will stop there and we can step forwards one instruction at a time from

* that point. Here, I am setting the breakpoint

* at the _start label.

* (gdb) break *_start

* (gdb) run

* (gdb) info rgisters

* GDB has the ability of disassembling the machine code back to assembly instructions. The command is “disassemble”.

Gdb layout asm

Gdb si (stepinto)

* To start the program, use command “run” *GD

B

Page 45: C from hello world to 010101

*Debug& assembly with with GUI

*Install Code::Blocks IDE

*To install Code::Blocks IDE, use the following command at the command prompt and all the required software will be installed.

*$ sudo apt-get install codeblocks

Page 46: C from hello world to 010101

*The assembly code generated from the C code is different from the basic Assembly code.s

A compiler has to produce working machine code for the infinite number of programs that can bewritten in the language it compiles. It is impossible to ensure that all possible highlevel Instructions are translated in the optimum way;

Call assembly into C

Page 47: C from hello world to 010101

*Built own OS

Page 48: C from hello world to 010101

*Raspi processor

How a Raspberr y-Pi processor boots. The BCM2385 includes a GPU and this GPU includes abootloader . The bootloader is capabable of reading the contents of a FAT32 partition on an SD card and booting fr omthe kernel .img file contained on it. This kernel.img file is an ARM executable, and is generally the linux kernel . All we need to do is generate our executable and replace the kernel .img file on the SD card with our file to execute it.The first thing we will need to setup is the GPIO controller. There are no drivers we can rely on as there is no OS running, all the bootloader has done is boot the processor into a working state, ready to start loading the OS.

Page 49: C from hello world to 010101

*Now that you have extracted the template, create a new file in the 'source' directory called 'main.s'. This file will contain the code for this operating system. To be explicit, the folder structure should look like:

*build/ (empty)

* source/

main.s

*kernel.ld

*LICENSE

*Makefile

Open 'main.s' in a text editor so that we can begin typing assembly code. The Raspberry Pi uses a variety of assembly code called ARMv6, so that is what we'll need to write in.Copy in these first commands..section .init.globl _start_start:

*Hello World OS

Page 50: C from hello world to 010101

*This will turn on the LED and blink

To install your operating system, first of all get a Raspberry PI SD card which has an operating system installed already. If you browse the files in the SD card, you should see one called kernel.img. Rename this file to something else, such as kernel_linux.img. Then, copy the file kernel.img that make generated onto the SD Card. You've just replaced the existing operating system with your own. To switch back, simply delete your kernel.img file, and rename the other one back to kernel.img. I find it is always helpful to keep a backup of you original Raspberry Pi operating system, in case you need it again.

Page 51: C from hello world to 010101

BareMetal OS, a 64-bit operating system written entirely in assembly.

APOTHEMEOS A Small Assembly Opensource Os.

Page 52: C from hello world to 010101

*Read more

*Cambridge tutorials by lighting the OK LED on the Raspberry-Pi board.

*Any request : [email protected]

Page 53: C from hello world to 010101

*Thank you