Estratto del documento

Assembly assembly

Controllo di condizione

IF (x == 1) {
// CODE Block A
} ELSE IF (x == 2) {
// CODE Block B
} ELSE {
// CODE Block C
}

CMPB $1, %AL
JNZ .ELSEIF
# CODE Block A
JMP .ENDIF
.ELSEIF :
CMPB $2, %AL
JNZ .ELSE
# CODE Block B
JMP .ENDIF
.ELSE
# CODE Block C
.ENDIF ;

Aggiornamento carry flag

a - b richiede prestito quando b > a

  • Se addizione non c'è riporto, c'è un prestito
  • Se addizione c'è riporto, non c'è prestito

CF = 1 se c'è riporto, ZF = 1 se risultato zero

Condizione Primo controllo Secondo controllo
dest < source CF = 1
dest ≥ source CF = 0
dest > source CF = 0 ZF = 0
dest = source ZF = 1
dest ≠ source ZF = 0

In aritmetica segnata

Chiediamo DEST-SRC < 0.

Risultato dato dal segno SF.

Se c'è stato overflow, il segno è cambiato.

OF = 1 se riporti diversi, OF = 0 riporti uguali.

Confronti in aritmetica segnata

.org 0x800
.data
x: .word 3
y: .word -2
.text

# Imposta a 1 l’indirizzo 0x1280 solo se x > y
# Assumo che x ed y possano assumere valori negativi
movw x, %ax
movw y, %bx
cmpw %bx, %ax
jz .nonImpostare
js .SFSet
jo .nonImpostare # eseguita se SF = 0. Se OF = 1 allora SF != OF
jmp .set
.SFSet:
jno .nonImpostare # eseguita se SF = 1. Se OF = 0 allora Sf != OF
.set:
movb $1, 0x1280
.nonImpostare:
hlt

Cicli

while(TEST) {
CODE;
}

do {
CODE;
} while(TEST);

for(INIT; TEST; POST) {
CODE;
}

Tipi di variabili in C

In C ogni variabile ha un tipo.

  • Tipi primitivi (interi, virgola mobile, ecc.)
  • Tipi aggregati (struct, union)
  • Puntatori
  • Variabili globali: occupano memoria nelle sezioni .DATA e .bss visibili da tutte le funzioni
  • Variabili locali: occupano memoria all'interno dello stack, visibili alla funzione stessa

La finestra di stack (o record di attivazione)

void function() {
int x = 128;
...
return;
}

function:
pushq %rbp
movq %rsp, %rbp
subq $4, %rsp
movl $128, -4(%rbp)
...
leave
ret

  • L'istruzione x86 leave invalida la finestra di stack corrente
  • Corrisponde a: movl %rbp, %rsp; popl %rbp
  • Esiste anche l'istruzione enter, ma non è efficiente
  • I debugger usano le finestre di stack per ricostruire le chiamate effettuate

Calling convention z64/x86

Primi 6 parametri di una subroutine sono passati tramite registri:
RDI, RSI, RDX, RCX, R8, R9

Si utilizza lo stack per quelli aggiuntivi.

Due registri per il valore di ritorno: RAX e RDX.

Registri:
Callee - save: RBP, RBX, R12 - R15
Caller - save: tutti gli altri

Anatomia dello stack

void f(int first, int second, int third, int fourth, int fifth, int sixth, int seventh, int eighth,) {
int x, y;
...
}

Tipi primitivi

In C sono 4: CHAR, INT, FLOAT, DOUBLE.

Alterati usando: SIGNED, UNSIGNED.

I modificatori signed, unsigned indicano al compilatore se devono essere utilizzate istruzioni aritmetiche per lavorare o meno in complemento a 2 e quali sono i bit di FLAGS da controllare per effettuare salti condizionali.

Tipo C Dimensione dato
CHAR BYTE
INT WORD
FLOAT LONG WORD
DOUBLE QUADWORD

Cast: conversione tra tipi.

L'operazione di cast converte un dato da un tipo all’altro: (tipo di destinazione)variabile;

Ad esempio:
int integer = 10;
double real = (double)integer;

La conversione tra tipi interi viene realizzata mediante le istruzioni movsx e movzx oppure troncando la parte più significativa.

Il tipo booleano

Dal punto di vista architetturale, il tipo “booleano” non esiste.

Non esiste alcuna istruzione in nessuna ISA che gestisca i booleani.

Per convenzione: 0 è false, un valore diverso da 0 è true.

char booleano = 1;
if(booleano)
printf("true\n");

Il controllo sui booleani può essere realizzato con le istruzioni jz/jnz.

Array

Collezione di elementi, ciascuno identificato con un indice.

Si usa base o spiazzamento per inizio array.

Si usa indice e scala per indirizzo elemento preciso.

movq $0, %rcx # %rcx viene usato come indice
movq $array, %rax # %rax viene usato come base
.loop:
movq (%rax, %rcx, 8), %rdx # carica il dato nella CPU
# addq $1, %rcx
cmpq $size, %rcx
jnz .loop

movq $0, %rcx # %rcx viene usato come indice
.loop:
movq array(, %rcx, 8), %rdx # carica il dato nella CPU
# addq $1, %rcx
cmpq $size, %rcx
jnz .loop

Se vettore non è composto da tipi primitivi, si usa registro puntatore, che deve essere incrementato.

movq $array, %rax # carica indirizzo del primo elemento
movq $size, %rcx
.loop:
movq (%rax), %rdx # carica il dato nella CPU
# addq $element_size, %rax incremento
subq $1, %rcx
jnz .loop

Stringhe

Vettori di char, il cui ultimo elemento è il Terminatore di stringa.

Matrici

Strutture dati a più dimensioni, "linearizzate" in memoria.

ADDRESS ⟺ i * N * size + j * size

Puntatori

Tipo di dato che contiene indirizzo di memoria di una variabile.

INT * INTPTR

Esiste un generico puntatore a memoria: VOID *

Puntatori: equivalente in assembly

L’utilizzo dei puntatori in assembly è immediato.

L’indirizzo dell’area da puntare viene scritto in un registro.

Si utilizza quel registro come registro base.

Il contenuto del registro può essere manipolato a piacimento.

int var;
int *ptr = &var;
*ptr = 42;
ptr++;

movq $var, ptr
movq ptr, %rax
movl $42, (%rax)
addq $4, %rax

Strutture

Modo per aggregare tipi primitivi o vettori.

struct book {
char title[10];
char author[10];
int year;
int price;
};

Per accedere ai membri di una struttura in assembly, si può utilizzare la modalità di indirizzamento generale.

Si calcola uno spiazzamento a partire dalla base della struct.

Si carica in un registro l’indirizzo iniziale della struct.

Si utilizza un operando in memoria composto da spiazzamento e base.

Attenzione al padding se si interagisce con codice generato da un compilatore.

struct book {
char title[10];
char author[10];
int publication_year;
float price;
};
struct book b;
b.publication_year = 1987;

In C il passaggio di parametri è sempre fatto per valore.

Funzione riceve copia del parametro.

Effettuata copia di tutta la struttura.

Usare puntatori per passaggio per riferimento (indirizzo).

Passaggio di parametri

struct huge {
char member[4096];
};
extern void f1(struct huge s);
extern void f2(struct huge *s);
struct huge glbl;
void f(void) {
f2(&glbl);
}

pushq %rbp
movq %rsp, %rbp
movq $glbl, %rdi
call f2
popq %rbp
ret

Caso in cui uso puntatore.

Passaggio di parametri

struct huge {
char member[4096];
};
extern void f1(struct huge s);
extern void f2(struct huge *s);
struct huge glbl;
void f(void) {
f1(glbl);
}

pushq %rbp
movq %rsp, %rbp
subq $4096, %rsp
movq %rsp, %rdi
movq $glbl, %rsi
movq $512, %rcx
cld
rep movsq
call f1
addq $4096, %rsp
leave
ret

Caso in cui copio tutta la struttura.

Movs e stos

  • Si tratta di istruzioni per operare su stringhe (buffer di dati)
  • Utilizzano dei registri impliciti:
    • RCX: contatore del numero di operazioni elementari da eseguire
    • RSI: indirizzo sorgente (per il movimento)
    • RDI: indirizzo destinazione
    • RAX: valore cui impostare la memoria (per l’impostazione)
  • Il direction flag (DF) identifica la direzione dell’operazione:
    • DF = 0: l’operazione di copia si svolge in avanti
    • DF = 1: l’operazione di copia si svolge all’indietro

movs: move data from string to string
stos: store string

movq $source, %rsi
movq $destination, %rdi
movq $size/8, %rcx
cld
movsq

movq $0x0, %rax
movq $destination, %rdi
movq $size/8, %rcx
cld
stosq

Se sorgente e destinazione sono sovrapposte, una copia in avanti può portare ad un risultato errato.

movb $src, %rsi
movb $dst, %rdi
movb $size, %rcx
cld
movsb

Soluzione: effettuare la copia all’indietro.

Se la sorgente e la destinazione sono sovrapposte, una copia in avanti può portare a un risultato errato.

Soluzione: effettuare la copia all'indietro.

RSI e RDI puntano alla fine dei buffer coinvolti.

std configura il processore per fare la copia all'indietro.

Equivalenti in C

#include <string.h>

void *memcpy(void *restrict dest, const void *restrict src, size_t n);
Effettua una copia memoria/memoria in avanti.

void *memmove(void *dest, const void *src, size_t n);
Effettua una copia memoria/memoria all'indietro (i buffer possono sovrapporsi).

void *memset(void *s, int c, size_t n);
Imposta un’area di memoria al valore c.

Unione

Blocco di memoria per conservare variabili differenti.

union number {
short little_number;
int large_number;
double fractional_number;
} numbers

Maschere di bit: forzatura

Per forzare dei bit ad un valore specifico, si usano maschere di bit.

Per forzare un bit a 1, si utilizza l'istruzione or:

Forzatura a 1 del bit più significativo: orl $0x80000000, %eax

Per forzare un bit a 0, si utilizza l'istruzione and:

Forzatura a 0 del bit più significativo: andl $0x7FFFFFFF, %eax

Per invertire un bit, si utilizza l'istruzione xor:

Inversione dell'ultimo bit: xorl $0x80000000, %eax

Per azzerare un registro, si possono usare due istruzioni equivalenti:

movq $0, %rax
xorq %rax, %rax

La seconda è preferibile perché più efficiente.

Si possono comporre maschere di bit per forzare più bit contemporaneamente.

Maschere di bit: estrazione

Supponiamo di avere un numero a 32 bit e di voler estrarre il valore dei 3 bit meno significativi.

Si costruisce una maschera di bit del tipo 000....00111, equivalente a 7.

Estrazione dei bit: andl $7, %eax

Per verificare se i bit sono a zero: testl $7, %eax

Che cosa fa l'istruzione testq $2, %rax?

Che cosa fa l'istruzione testq %rax, %rax?

Anteprima
Vedrai una selezione di 4 pagine su 15
Assembly Pag. 1 Assembly Pag. 2
Anteprima di 4 pagg. su 15.
Scarica il documento per vederlo tutto.
Assembly Pag. 6
Anteprima di 4 pagg. su 15.
Scarica il documento per vederlo tutto.
Assembly Pag. 11
1 su 15
D/illustrazione/soddisfatti o rimborsati
Acquista con carta o PayPal
Scarica i documenti tutte le volte che vuoi
Dettagli
SSD
Ingegneria industriale e dell'informazione ING-INF/05 Sistemi di elaborazione delle informazioni

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher davidescri di informazioni apprese con la frequenza delle lezioni di Calcolatori elettronici e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Università degli Studi di Roma Tor Vergata o del prof Pellegrini Alessandro.
Appunti correlati Invia appunti e guadagna

Domande e risposte

Hai bisogno di aiuto?
Chiedi alla community