0% found this document useful (0 votes)
63 views

E91 (11) C&asm

The document discusses using C and assembly language together. It provides examples of how information can be passed between functions written in C and assembly using registers and stack memory. Arguments are passed in registers R12-R15, return values in R12. Global variables can be accessed directly in assembly code. Assembly language can be used within C to optimize performance-critical sections.

Uploaded by

Alekso Gjakovski
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
63 views

E91 (11) C&asm

The document discusses using C and assembly language together. It provides examples of how information can be passed between functions written in C and assembly using registers and stack memory. Arguments are passed in registers R12-R15, return values in R12. Global variables can be accessed directly in assembly code. Assembly language can be used within C to optimize performance-critical sections.

Uploaded by

Alekso Gjakovski
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

C & ASM

C & ASM

Using the languages together
C and Assembler Together
C and Assembler Together
• C
C & ASM need not be used separately.
& ASM need not be used separately
• Within “C” you can insert assembly language 
using “asm(“ nop”);
using  nop”) ”
• ASM is generally used to speed up C code.
– Typically a function is written in assembler, and 
called from C.
– How is information passed between the two?
Let’s See how C does it
// Add two numbers.
int add2_c(int a1, int a2) { Stack (Initial) Stack (w/ locals)
int a3;
a3 = a1 + a2; Mem Data Mem Data
return(a3); SP=200 200
}
1FE 1FE k
main() { 1FC 1FC j
volatile int i, j, k;
1FA SP=1FA i
i = 3;
3 j = 5
5; 1F8 1F8
1F4 1F4
// Call "C" to add two numbers
k = add2_c(i,j); 1F2 1F2
} 1F0 1F0
1EF 1EF
10 main() {
main:
0x03122: 8031 0006 SUB.W #0x0006,SP
13 i=3; j=5; Performing the function call
Performing the function call
0x03126: 40B1 0003 0000 MOV.W #0x0003,0x0000(SP) • move 1st argument, i, into R12
0x0312C: 40B1 0005 0002 MOV.W #0x0005,0x0002(SP) • move 2nd arg, j, into R13
// Call "C" to add two numbers
15 k = add2_c(i
add2 c(i ,j); • call function
0x03132: 412C MOV.W @SP,R12 • move result from R12 to k
0x03134: 411D 0002 MOV.W 0x0002(SP),R13
0x03138: 13B0 3158 CALLA #add2_c
0x0313C: 4C81 0004 MOV.W R12,0x0004(SP) Remember, 1st arg in R12, 2nd in R13
int add2_c(int a1, int a2) {
int a3;
a3 = a1 + a2;
What happens in function?
return(a3);
} Stack (after call)
Stack (after call) Stack (in func)
Stack (in func) Stack (clean)
Stack (clean)
Mem Data Mem Data Mem Data
Remember,  Stack (w/ locals)
1st arg in R12,  200 200 200
Mem Data
2nd in R13 1FE k 1FE k 1FE k
200
1FC j 1FC j 1FC j
1FE k
1FA i 1FA i 1FA i
1FC j
SP=1F8 old PC 1F8 old PC SP=1F8 old PC
SP 1FA
SP=1FA i
1F4 1F4 a3 1F4 a3
1F8
1F2 1F2 a2 1F2 a2
1F4
1F0 SP=1F0 a1 1F0 a1
1F2
1EF 1EF 1EF
1F0
1EF In function
• Set up stack
0x03148: 8031 0006 SUB.W #0x0006,SP • Move args into locals
0x0314C: 4D81 0002 MOV.W R13,0x0002(SP)
0x03150: 4C81 0000 MOV.W R12,0x0000(SP)
• Move a2 to R15
0x03154: 411F 0002 MOV.W 0x0002(SP),R15 • Add a1 to R15 (i.e., a2)
0x03158: 512F ADD.W @SP,R15 • Move R15 to a3
Move R15 to a3
0x0315A: 4F81 0004 MOV.W R15,0x0004(SP) • Move a3 (the result) into R12
0x0315E: 411C 0004 MOV.W 0x0004(SP),R12
0x03162: 5031 0006 ADD.W #0x0006,SP • Clean up stack
0x03166: 0110 RETA • Return
Can we do better with ASM?
main()
i () {
volatile int i, j, k;

i = 3; j = 5;

// Call “ASM" to add two numbers


k = add2_asm(i,j);
}

.cdecls C,LIST, "msp430fg4618.h"


.global add2_asm ASM function
;--------------.text segment is
i for code--- • Share header with “C”
Sh h d ith “C”
.text • Declare function “global” so linker finds it.
;------------------------------------------
add2_asm add.w R13, R12 • Put code in “text” section
reta • Label “add2_asm”
_
.end • Add 2nd arg to 1st and return this value
• Return
• End of ASM

To be fair, the compiler generates the same 
code from the function add2_c if  
optimizations are turned on.
Rules for passing arguments 
and using registers
and using registers
In function 
• Registers R11 through R15 can be used without saving values  registers are:
(except when using ISR) • R12 = i1
• Caller places first arguments in registers R12‐R15, in that order.    • R13 = i2
• R14 = i3
(If more arguments, put on stack ‐ more about this below)
• R15 = i4
– ints require  one register (16 bits)
– chars (8 bits) use one register Stack (in function)
– long ints and floats use two registers (32 bits) Mem Data
– a pointer to an array passes its address (16 bits) – (example later) 1F0
??
(arbitrary)
• Return values are placed in R12 (or R12, R13 if 32 bits).
( )
1EE i6
1EC i5
1EA old PC

int manyVars(int a1, int a2, int a3, int a4, int a5, int a6) { 1E8 a6
return (a1 + a2 + a3 + a4 + a5 + a6); 1E6 a5
}
1E4 a4
main() {
volatile int i1, i2, i3, i4, i5, i6, k; 1F2 a3
1E0 a2
k = manyVars(i1, i2, i3, i4, i5, i6);
} SP=1DE a1
Global variables
Global variables
int n_g=4; // Global variable .cdecls C,LIST, "msp430fg4618.h"
.global add2_asm
// Add three numbers
numbers, one global .global
global n_g
n g
int add2_c(int a1, int a2) { ;-------------------.text----------
volatile int a3; .text
a3 = a1 + a2 + ng; ;----------------------------------
return(a3); add2_asm add.w R13, R12
} add.w &n_g, R12
Main () { reta
volatile int i, j, k; .end
i=2; j=3;

k = add2_c(i, j);

k = add2_asm(i, j);
}
Example
• Weighted average (i.e., FIR filter) N −1

• yi is output, xi is input: y = ∑ b x i
k =0
k i −k

• Example weighted sum with middle point 
g
weighted twice as much as others:
b = {0.25, 0.50, 0.25}
2
yi = ∑b x
k =0
k i −k =0
0.25x
25xi−2 + 0.50x
0 50xi−1 + 0.25x
0 25xi

• Very powerful technique at heart of digital 
signal processing
l
• Without loss of generality we can restate as:
N −1
y = ∑ b x where the xk = most recent inputs
i k k
k =0
Implement FIR in C
main() {
const int n=3;
const int b[]={0x2aaa, 0x2aaa, 0x2aaa}; // 1/3, 1/3, 1/3 (weights - Q15)
int x[]={0x4000, 0x4000, 0x4000}; // last values of input
int y; // O
Output
tp t

y = fir_c (b, x, n);

int fir_c(const int *b, int *x, int n) {


long sum=0;
int i;
for (i=0; i<n; i++)
sum += (long) b[n] * x[n]; // Q15*Q15 is Q30
return((int) (sum>>15)); // Q30 to Q15
}

For 3 weights:  353 cycles   or   118 cycles/weight   
For 100 weights:  8792 cycles   or   88 cycles/weight   
16 bit multiplier/accumulator (MAC)

If OP1 and OP2 are Q15, RESHI:RESLO is Q30.
Implement FIR in ASM
main() {
constt int
i t n=3;
3
const int b[]={0x2aaa, 0x2aaa, 0x2aaa};
int x[]={0x4000, 0x4000, 0x4000};
int y;

y = fir_asm
fir asm (b, x, n);
}

.global fir_asm
;----------------------------
.text
;----------------------------
fir_asm mov #0, &RESHI
FIR in ASM
mov #0, &RESLO
fir loop
fir_loop mov @r12+, &MACS • Clear result register
g
mov @r13+, &OP2 • Move b[0] into MACS, increment pointer
dec r14 • Move x[0] into OP2, increment pointer
jnz fir_loop
rlc &RESLO (this performs mult/accum)
rlc
l &RESHI • Decrement n, check for zero, loop
Decrement n check for zero loop
mov &RESHI, r12 • Left shift RESLO, MSB into Carry
reta
• Left shift RESHI, Carry into LSB
.end
• Mover RESHI into result and return

For 3 weights:  74 cycles   or   25 cycles/weight  (4.8 times faster than C)   
For 100 weights:  1141 cycles   or   11 cycles/weight  (7.7 times faster than C)   
Can we make C faster with pointers?
int fir_c(const int *b, int *x, int n) {
long sum=0;
while (--n>=0) Yes – but only about 5%
sum += (long) (*b++) * (*x++);
return((int) (sum>>15));
}

U i ASM
Using ASM routines in practice
ti i ti
In practice: write and debug routine in C, then convert to assembler (perhaps using 
compiled C code as template)
compiled C code as template)

References
• MSP430x4xx Family User’s Guide http://focus.ti.com/lit/ug/slau056j/slau056j.pdf
• MSP430 Optimizing C/C++ Compiler v 3.3 User's Guide http://focus.ti.com/lit/ug/slau132e/slau132e.pdf
• MSP430 Assembly Language Tools v 3.3 User's Guide http://focus.ti.com/lit/ug/slau131e/slau131e.pdf

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy