# Cours ASM **Important:** Ces notes sont les notes que j'utilise pour préparer les séances de RMD afin d'être à la page sur ce que vous êtes supposés savoir si vous avez vu le cours, **il ne s'agit donc pas d'un résumé du cours** et il peut manquer des infos importantes. ## Cours 1 - Processor Architecture Opti avant = taille du code Opti mtn = efficacité du code Assembleur: contrôle total des instructions Endianness: ordre des bytes - control unit = pour gérer les différents acteurs - ALU (arithmetic and logical unit) = pour compute l'info - register bank = pour stocker l'info We need more to execute complex tasks: - program memory access - data memory access Il faut le moins d'accès mémoire possible pour un truc un minimum performant - caches, mmu (memory management unit = translation between pmem and vmem, cache control, ...) - different units depending on the data type (integer, floating-point, control, ...) Today, tout est le même chip -> avant, chaque unit était indépendante (plus lent, moins compact) Unit: - fetches and decode instruction - registers give data - ALU implements operation - logical ops = AND, OR, XOR, NOT, NOR - arithmetic ops = add, sub, mul (not div, requires registers) - shifts - compares - (some instruction may need external data) Registers: may be seen as variables inside the proc, size depends on the proc General-purpose registers: (vol. 1, p. 68) - int (rax, ebx, ...) - floating-point (ymm0, xmm1, ...) Specialized registers: - flags: zero, neg, carry... - system: mode Microprogrammed proc = different steps of processing an instruction, but only one at a time, for instance: - `sub`: fetch, decod, exec, write - `jmp`: fetch, decod, exec - `ld` (= load): fetch, decod, exec, mem (= memory access), write ![](https://i.imgur.com/zGEF9ZP.png) Cons: - slow because you need to wait for previous step to complete - more complex = longer - most of hardware only used once for each instruction (you don't `fetch` twice...) - most of hardware unused (for instance, when ALU works, nothing else does) Pros: easy, small, and adding instructions is ez af too (only add it in `decode` + add sequence in `exec`) => opti = **pipelined** proc: le proco fonctionne à flux tendu - split exec in several steps - each step is a basic op - each step is associated with a specific hardware part - all those parts works in parallel ![](https://i.imgur.com/PgVphkZ.png) => speed up the pipeline by splitting the slowest operation CISC (complex instruction set computer) = instructions complexes qui permettent de faire beaucoup de choses - pros: 1 instruction peut faire beaucoup de choses, beaucoup d'operations, easier to write and to compress - cons: variable-len instructions, requires complex hardware RISC (reduced instruction set computer) = une instruction = 1 opération, on fait qu'une chose à la fois - pros: simple, fixed-len instructions, decoding requires simple hardware - cons: longer programs, harder to optimize -> modern procs often translate CISC to RISC ## Cours 2 - Memory Used to: - fetch instructions - access data Von Neuman architecture: data et instructions au même espace d'adressage Harvard architecture: data et instructions dans 2 espaces mémoires physiques séparés **Immediate addressing** - *value* of data is directly stored in the *instruction* - no memory access needed ```x86asm add $2, %rdi ``` **Absolute addressing** - *address* of data is stored directly in the *instruction* (ultra rare, on sait rarement où se situe la data qui nous intéresse) - memory access needed to get value inside the address ```x86asm mov [0x830], %rdi ``` **Register indirect addressing** - *address* of data is stored in a *register* - memory access needed to get value inside the address stored in the register ```x86asm mov [%rsi], %rdi ``` **Complex addressing** - Register indirect with base register - Register indirect with offset - ... ```x86asm mov [%rsi + 0x123], %rdi mov [%rsi + %rax], %rdi ``` Alignement est une histoire de data type width, les accès non-alignés sont beaucoup plus lents, parfois même interdits selon les procs In a structure, fields are stored in declaration order and they must all be aligned ![](https://i.imgur.com/OAPipzd.png) Si on a pas un cas idéal comme au dessus, le compilo add du padding pour garder l'alignement ![](https://i.imgur.com/VtY3SBq.png) = gain de vitesse mais perte de place (padding bytes are unused) Avec `__attribute__((packed))` on peut forcer le fait de ne pas aligner les fields = pas de padding donc moins rapide mais pas de perte de place (en vrai c'est rarement utile à notre niveau) **Endianness** = le sens dans lequel on lit la donnée i.e. si le "poids fort" est à droite ou à gauche **Cache memory**: - local copy of central memory - transparent (invisible pour nous) - volatile = peut être flushed à tout moment - faster, closer to CPU - mais cher Plusieurs caches de différentes taille, vitesses, latences... Chaque cache est à une distance différente du CPU Memory address space in contiguous (physically) and be mapped to another address space (virtually) La mémoire est découpée en segments qu'on définit par: - segment base address in target address space (début du segment) - segment size - segment type and access rights (read, write, execute) Pour gérer les segments: segment descriptor table Limitations: - address-space must be mapped at contiguous blocks donc compliqué d'extend un segment - on ne peut pas avoir de "bouts de segments" Modern OS use **pages** to split address space. On les définit par - address in target address space - type + access rights - size - other: cachability, ... Pour gérer les pages: page descriptor table Better than segments: - addresses spaces may be mapped to uncontiguous target page (remember malloc) - sharing, swapping... **Memory protection** to protect: - system from hosted processes - hosted processes from each other `cr3` est registre qui hold le PDBR (Page Directory Base Register) qui permet d'accéder aux pages d'un process Branch principle: modify execution flow - `call` = save return address (pushed onto the stack) - `jmp` = nothing is saved, flow execution just go to destination - `jge`, `jne`, ... = conditional jump (WIP - à terminer) ## Cours 3 - Handling events and OS generalities *interrupt*: caused by external event *exception*: caused by instruction execution *synchronous*: vient d'un effet du code, on peut plus ou moins le prévoir (syscall, page fault, ...) *asynchronous*: indépendant du code, interruption qui vient de l'exterieur (appuyer sur une touche du clavier, problème hardware, ...) On peut voir ça comme "synchronisé avec l'exécution d'une instruction" **User mode** can access user space only **Kernel mode** can access both user space and kernel space Trap handler table: contient les routines à suivre pour chaque interruption Syscalls: - execute process, exit - read input, write ouput, ... - perform restricted actions (accessing hardware devices or the MMU) - ... Processor modes to ensure process isolation: user mode (user applications) / supervisor mode (system kernel operations) On peut voir les syscalls comme des moyens d'accéder aux services que le kernel met à notre disposition (comme une grosse API) ![](https://i.imgur.com/NvPzoj8.png) Faults: - conséquence de l'exécution de certaines instructions - kernel exception handler may return to faulty user context - syscalls are deliberate, faults are unexpected (et pas voulues) To handle a fault, the OS can: - kill user process - notify process about the fault so it may resolve it itself - solve the problem and resume transparently ![](https://i.imgur.com/Tj7GaBO.png) To perform **multitasking**, OS has to: - create and delete processes - organize processes in memory - schedule processes for CPU use The idea is simulationg execution of concurrent execution of many processes as one may not use system ressources at full capacity ![](https://i.imgur.com/LUYW3F5.png) Important: ![](https://i.imgur.com/5vGCw8g.png)