Calcolatori Elettronici II
Programmazione C/Assembler
per i processori ARM
Prof. A. Mazzeo
Dipartimento di Informatica e Sistemistica
Università Degli Studi di Napoli Federico II
DIS - Dipartimento di Informatica e Sistemistica
Programmazione mista C/Assembly


Le routines che effettuato chiamate ad altri moduli
devono rispettare convenzioni comuni per i parametri
passati e ricevuti
Per il processore ARM queste convenzioni sono espresse
dall’ARM Procedure Call Standard (APCS)
DIS - Dipartimento di Informatica e Sistemistica
Lo standard APC


APCS è un insieme di regole per la chiamata di
funzioni in segmenti di codici compilati o
assemblati separatamente
Definisce:
»
»
»
»

I vincoli nell’uso dei registri
Convenzioni per lo stack
Il formato di uno stack backtrace data structure
Il supporto ai meccanismi di condivisione delle librerie di ARM
Esistono diverse versioni di APCS, non compatibili
tra loro, fra cui il programmatore deve scegliere
DIS - Dipartimento di Informatica e Sistemistica
Chiamata di una routine ASSEMBLY da C

La routine assembly invocata nel programma C
deve essere esportata
AREA |mul64$$code|, CODE, READONLY
EXPORT mul64
mul64
MOV
MOV

ip, a1, LSR #16 ;ip = a_hi
a4, a2, LSR #16 ;a4 = b_hi
Il programma C deve dichiarare che utilizzerà
una funzione implementata esternamente
extern int64 mul64(unsigned a, unsigned b);
DIS - Dipartimento di Informatica e Sistemistica
Chiamata di una routine ASSEMBLY da C

Esporta
il simbolo C
La routine assembly invocata nel
programma
per renderlo visibile
deve essere esportata
all’esterno
AREA |mul64$$code|, CODE, READONLY
EXPORT mul64
mul64
MOV
MOV

ip, a1, LSR #16 ;ip = a_hi
a4, a2, LSR #16 ;a4 = b_hi
Il programma C deve dichiarare che utilizzerà
una funzione implementata esternamente
extern int64 mul64(unsigned a, unsignedip
b); <-parte alta di a
a4 <-parte alta di b
DIS - Dipartimento di Informatica e Sistemistica
Uso e denominazione dei registri

Tutti i registri che non sono utilizzati nel ruolo per essi definito
dall’APCS possono essere usati come registri generali
DIS - Dipartimento di Informatica e Sistemistica
Perché programmare in Assembly 1/5



Realizzare la somma tra due interi a 64 bit
Un programma C che realizzi una tale operazione non ha accesso al
flag di carry dello Status Register
Il programma C a tale scopo realizzato
(ARM_home\examples\candasm\ADD64_1.C) potrebbe essere:
void add_64(int64 *dest, int64 *src1, int64 *src2)
{
unsigned hibit1=src1->lo >> 31, hibit2=src2->lo >> 31, hibit3;
dest->lo=src1->lo + src2->lo;
hibit3=dest->lo >> 31;
dest->hi=src1->hi + src2->hi +
((hibit1 & hibit2) || (hibit1!= hibit3));
return;
}
DIS - Dipartimento di Informatica e Sistemistica
Perché programmare in Assembly 2/5

Compilare il file add64_1.c
 armcc –apcs 3/32bit –S add64_1.c
» Il flag –apcs 3/32bit forza l’utilizzo dell’APCS 3
nella versione a 32 bit
» Visualizzare il file add64_1.s contenente il codice
assembly generato
DIS - Dipartimento di Informatica e Sistemistica
Perché programmare in Assembly 3/5
AREA |C$$code|, CODE, READONLY
|x$codeseg| DATA
add_64
STMDB sp!,{v1,lr}
LDR
v1,[a2,#0]
MOV a4,v1,LSR #31
LDR ip,[a3,#0]
MOV lr,ip,LSR #31
ADD
ip,v1,ip
STR ip,[a1,#0]
MOV ip,ip,LSR #31
LDR
a2,[a2,#4]
LDR
a3,[a3,#4]
ADD
a2,a2,a3
TST a4,lr
TEQEQ a4,ip
MOVNE a3,#1
MOVEQ a3,#0
ADD
a2,a2,a3
STR a2,[a1,#4]!
LDMIA sp!,{v1,pc}
AREA |C$$data|,DATA
|x$dataseg|
EXPORT add_64
END
È immediato verificare
che il codice ottenuto
non risulta essere
efficiente
DIS - Dipartimento di Informatica e Sistemistica
Perché programmare in Assembly 3/5
AREA |C$$code|, CODE, READONLY
|x$codeseg| DATA
add_64
STMDB sp!,{v1,lr}
LDR
v1,[a2,#0]
MOV a4,v1,LSR #31
LDR ip,[a3,#0]
MOV lr,ip,LSR #31
ADD
ip,v1,ip
STR ip,[a1,#0]
MOV ip,ip,LSR #31
LDR
a2,[a2,#4]
LDR
a3,[a3,#4]
ADD
a2,a2,a3
TST a4,lr
TEQEQ a4,ip
MOVNE a3,#1
MOVEQ a3,#0
ADD
a2,a2,a3
STR a2,[a1,#4]!
LDMIA sp!,{v1,pc}
AREA |C$$data|,DATA
|x$dataseg|
EXPORT add_64
END
È immediato verificare
che il codice ottenuto
non risulta essere
efficiente
INFATTI
ACCEDE ALLO STACK
ANCHE PER UN SALVATAGGIO
DI CONTESTO CHE COINVOLGE
POCHI REGISTRI RISPETTO
A QELLI DI CUI DISPONE
DIS - Dipartimento di Informatica e Sistemistica
Perché programmare in Assembly 3/5
Store a blocchi:
AREA |C$$code|, CODE, READONLY
|x$codeseg| DATA
add_64
STMDB sp!,{v1,lr}
LDR
v1,[a2,#0]
MOV a4,v1,LSR #31
LDR ip,[a3,#0]
MOV lr,ip,LSR #31
ADD
ip,v1,ip
STR ip,[a1,#0]
MOV ip,ip,LSR #31
LDR
a2,[a2,#4]
LDR
a3,[a3,#4]
ADD
a2,a2,a3
TST a4,lr
TEQEQ a4,ip
MOVNE a3,#1
MOVEQ a3,#0
ADD
a2,a2,a3
STR a2,[a1,#4]!
LDMIA sp!,{v1,pc}
AREA |C$$data|,DATA
|x$dataseg|
EXPORT add_64
END
Salva con una
istruzione
Più registri
a
immediato
verificare
partire da SP
È
che il codice ottenuto
non risulta essere
efficiente
Load a blocchi:
Carica con una
istruzione
più registri
DIS - Dipartimento di Informatica e Sistemistica
Perché programmare in Assembly 4/5

Partiamo da codice C per la somma a 64 bit
senza considerare il flag di Carry
(add64_2.c)
#include "int64.h"
void add_64(int64 *dest, int64 *src1, int64 *src2)
{ dest->lo=src1->lo + src2->lo;
dest->hi=src1->hi + src2->hi;
return;}

Ottenere il codice assembly
armcc –li –apcs 3/32bit –S add64_2.c
DIS - Dipartimento di Informatica e Sistemistica
Perché programmare in Assembly 5/5
Analizzando il codice si osserva che
la prima ADD produce la low order
word mentre la seconda la high
order word. Il codice desiderato
può essere ottenuto semplicemente
sostituendo la prima ADD con
ADDS (ADD e SET flag) e la
seconda con ADC (ADD with
Carry)
add_64
LDR a4,[a2,#0]
LDR ip,[a3,#0]
ADD
a4,a4,ip
ADDS a4,a4,ip
STR a4,[a1,#0]
LDR a2,[a2,#4]
LDR a3,[a3,#4]
ADD
a2,a2,a3
ADC a2,a2,a3
STR a2,[a1,#4]!
MOV pc,lr
DIS - Dipartimento di Informatica e Sistemistica
L’effetto dell’APCS




a1 contiene un puntatore alla struttura di output della
funzione
a2 ed a3 contengono i puntatori alle strutture passate in
input alla funzione
a4 ed ip sono utilizzati in luogo dei registri v per non
salvare il contenuto di tali registri sullo stack
Nessun registro è stato salvato sullo stack  per il ritorno
dalla funzione basta
 MOV pc,lr

Per ritornare un valore, ad esempio il valore del flag di
carry, usare il registro a1
 MOV a1, #0
 ADC a1, a1, #0
» Il codice è disponibile nel file (ARM_home\examples\candasm\add64_3.s)
DIS - Dipartimento di Informatica e Sistemistica
Salvataggio dei registri sullo stack
add_64
STMDB sp!,{v1,lr}
LDR v1,[a2,#0]
MOV a4,v1,LSR #31
LDR ip,[a3,#0]
MOV lr,ip,LSR #31
ADD
ip,v1,ip
STR ip,[a1,#0]
MOV ip,ip,LSR #31
LDR a2,[a2,#4]
LDR a3,[a3,#4]
ADD
a2,a2,a3
TST a4,lr
TEQEQ a4,ip
MOVNE a3,#1
MOVEQ a3,#0
ADD
a2,a2,a3
STR a2,[a1,#4]!
LDMIA sp!,{v1,pc}


Tornando alla prima
versione dell’assembly
possiamo osservare che
essendo utilizzati
localmente i registri v1
ed lr sono preservati
sullo stack
Il ritorno dalla funzione è
ottenibile mediante
LDMIA
sp!,{v1,pc}
DIS - Dipartimento di Informatica e Sistemistica
Dettagli sull’APCS 1/2


I registri sb, sl, fp, ip, sp sono utilizzati con funzioni
dedicate nell’APCS; laddove non dovessero essere
utilizzati per i ruoli definiti dall’APCS i registri
possono essere utilizzati come registri generali
Le funzioni definite dall’APCS per i registri dedicati:
» ip
» lr
Utilizzato esclusivamente durante le chiamate di funzione. È
convenzionalmente utilizzato come un registro locare. In
altri casi può essere utilizzato come un registro temporaneo
corruttibile
Contiene l’indirizzo di ritorno all’uscita dalla funzione. Può
essere utilizzato come registro temporaneo preservandone il
valore sullo stack. Quest’ultimo valore può essere
direttamente ricaricato nel PC
DIS - Dipartimento di Informatica e Sistemistica
Dettagli sull’APCS 2/2
» sp
» sl
» fp
» sb
stack pointer
stack limit , utilizzato se il controllo dei limiti
dello stack è esplicito (cioè realizzato dal codice
in occorrenza di un push sullo stack). Se il
controllo è implicito (effettuato dall’hardware) il
registro può essere utilizzato come v7.
frame pointer. Contiene o zero o un puntatore
all’ultimo frame generato sullo stack.
static base. Nel caso di codice rientrante consente
l’accesso ad un array di puntatori a dati statici.
Nel caso di codice non rientrante può essere
usato come v6.
DIS - Dipartimento di Informatica e Sistemistica
Passaggio e ritorno di strutture 1/3


Generalmente le strutture sono passate
attraverso registri o eventualmente (se le
dimensioni o il numero lo esigessero)
attraverso lo stack.
Il registro a1 punta all’area di memoria
utilizzata per la memorizzazione dei risultati
(per funzioni che ritornano strutture)
» È come se struct s f(int x) fosse compilata come
void f(struct s *result, int x)
DIS - Dipartimento di Informatica e Sistemistica
Ritorno di integer-like stuctures mediante registri 1/5


Utilizzando il registri come puntatori per lo
scambio di strutture si ha un overhead
elevato.
L’uso della keyword __value_in_regs forza il
passaggio delle strutture di dimensioni
inferiori alle quattro parole attraverso i
registri argomento a1-a4
DIS - Dipartimento di Informatica e Sistemistica
Ritorno di integer-like stuctures mediante registri 2/5




Problema: realizzare una routine
ottimizzata per il prodotto di interi a 64 bit.
Il codice C non sarebbe ottimizzato (C flag)
L’uso della memoria è da evitare.
Si consideri il codice contenuto nei file
mul64.s, mul64.h, int64.h e multest.c
DIS - Dipartimento di Informatica e Sistemistica
Ritorno di integer-like stuctures mediante registri 3/5

Il file mul64.s evidenzia
che la struttura è
ritornata attraverso i
registri a1 ed a2
Mul64 MOV ip, a1, LSR #16
MOV a4, a2, LSR #16
BIC a1, a1, ip, LSL #16
BIC a2, a2, a4, LSL #16
MUL a3, a1, a2
MUL a2, ip, a2
MUL a1, a4, a1
MUL a4, ip, a4
ADDS ip, a2, a1
ADDCS a4, a4, #&10000
ADDS a1, a3, ip, LSL #16
ADC a2, a4, ip, LSR #16
MOV pc, lr
DIS - Dipartimento di Informatica e Sistemistica
Ritorno di integer-like stuctures mediante registri 4/5

Affinché ciò avvenga nel file int64.h la funzione
mul64 è dichiarata come segue
__value_in_regs extern int64 mul64(unsigned a, unsigned b);

Per compilare, assemblare e lincare i file si
proceda come segue
armasm mul64.s –o mul64.o
armcc –c multest.c –apcs 3/32bit
Armlink mul64.o multest.o –o multest
DIS - Dipartimento di Informatica e Sistemistica
DIS - Dipartimento di Informatica e Sistemistica
Scarica

ARM_C-Assembler