Top Banner
CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!
21

CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

Jan 19, 2016

Download

Documents

David Walsh
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

1

Mixing C and assembly

Safety goggles on!

Page 2: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

2

Prelude: How do arguments get passed into a function when that function is called from C ?

And how do return values get passed back to the calling function from the called function?

Page 3: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CS-280Dr. Mark L. Hornick

3

What do compilers do?

C/C++ compilers generally Pass parameters using a register/stack

combination Return values via registers Save registers at the beginning of a function Restore registers before the function returns

Page 4: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810

Dr. Mark L. Hornick

4

Passing arguments among C functions

Every C compiler has it’s own rules and conventions for passing arguments to functions Arguments can be passed

1. via Registers

2. via the Stack

3. Both of the above

Page 5: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

5

GCC for Atmega32 uses Registers as much as possible to pass arguments

Consider a function: int16_t add( uint8_t x, uint16_t y);

uint8_t means “unsigned 8-bit int” uint16_t means “unsigned 16-bit int” int16_t means “signed 16-bit int” (same as int on Atmega32)

GNU GCC passes arguments left to right using registers r25 to r8 All arguments always take an even number of registersAll arguments always take an even number of registers

Above, value of x (single byte) is placed in r24:r25 (low, high bytes) The value of x is placed in r24 The value of 0 is placed in r25

Value of y (2 bytes) is placed in r22:r23 The low byte value of y is placed in r22 The high byte value of y is placed in r23

Note that r26:r31 are not used for passing arguments or return values since these registers are also the X, Y, and Z registers which the compiler uses for other purposes

What about the return value??

Page 6: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

6

GCC convention for returning values from functions

Return values always take an even number of registersReturn values always take an even number of registers 8-bit values are returned in r24:r25

Value in r24 0 in r25

16-bit values returned in r24:r25 Low byte in r24 High byte in r25

32-bit values returned in r22:r25 Lowest byte in r22 Highest byte in r25

64-bit values returned in r18:r25 lowest byte in lowest register

Page 7: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

7

Example of 2-byte argument passing

Consider the function: int add( int x, int y);

Size of int in C is dependent on processor On Atmega32, int is 2 bytes

Within MSVS for your PC, int means 4 bytes Note: Java int is always 4 bytes

GNU GCC passes arguments left to right using registers r25 to r8 All arguments always take an even number of registers

Above, value of x (two bytes) is placed in r24:r25 (low, high bytes) Value of y is placed in r23-r22

The return value is passed back in r24:r25 (low, high)

Page 8: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

8

Example of 4-byte argument passing

Consider the function: long add(int x, long y);

Size of long is 4 bytes

GNU GCC passes arguments left to right using registers r25 to r8

Above, value of x (2 bytes) is placed in r24:r25 r24 is low byte; r25 is high byte

Value of y is placed in r20:r23 r20 is lowest byte; r23 is highest byte

The return value is passed back in r22:r25 r22 is lowest byte

Page 9: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

9

What happens when we run out of registers to pass arguments?

Registers r25 to r8 can accommodate only 9 two-byte arguments 18 bytes total via registers

Consider the function: long add( long a, long b, long c, long d, long e);

20 bytes worth of arguments in this case

Page 10: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

10

When it runs out of Registers, the compiler uses the Stack to pass additional arguments

long add( long a, long b, long c, long d, long e);

20 bytes worth of arguments in this case, but only 18 1-byte registers are available

Approach: Arguments a, b, c, d (16 bytes total) are passed using registers r25 to r10 r22:r25 for a, r18:r21 for b The remaining argument e (4 bytes) is passed on

the Stack Leaving registers r8, r9 unused – the compiler

does not split an argument between Stack and Registers

Return addr (high)

Return addr (low)

e1 (low)

e2

e3

e4 (high)

???SP

Page 11: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

11

What do you think would happen here?

Consider the function: long add( long a, long b, long c, long d, int e, int f);

Also 20 bytes worth of arguments in this case

Page 12: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

12

The called subroutine must find the value of e on the Stack behind the return address

Example:long add( long a, long b,

long c, long d, long e);

Parameters a, b, c, d (16 bytes) are passed using registers r25 to r10 Remaining parameter e is passed as 4 bytes

on the Stack in the calling code: in ZH, SPH ; load SP to Zin ZL, SPL; Z points to cell containing ??? now.ldd temp, Z+3 ; load e1 to templdd temp, Z+4 ; load e2 to temp...

Return addr (high)

Return addr (low)

e1 (low)

e2

e3

e4 (high)

???SP

Page 13: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CE-2810Dr. Mark L. Hornick

13

General rules of register usage in mixed C/ASM

These rules apply when you write assembly subroutines that you’re mixing with compiler-generated code

R0 – used by compiler as a temporary register If you use R0 and then call code generated by the compiler, that

code may overwrite R0 R0 is not saved or restored by compiler-generated C code So save it before calling compiler code, and restore it afterwards

R1 – assumed to always be 0 by the compiler Save and clear it before calling compiler code, restore it after the compiler code

returns R2-R31 – used by compiler for various purposes

You must follow the compiler’s rules for register usage If you are calling compiler code:

Save these before calling; restore after the call returns If you are being called by compiler code:

Save first thing in your assembly subroutine; restore right before returning

Page 14: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CS-280Dr. Mark L. Hornick

14

C and Assembly inEmbedded Systems software

Entire program in C… …or mix C with assembly. Assembly is

generally used for… Critical code (size and efficiency) Accessing certain hardware Existing, proven code already written in assembly

Page 15: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CS-280Dr. Mark L. Hornick

15

Inline Assembly

Useful when writing mostly in C but a few assembly instructions are needed for… Calling assembly subroutines Accessing assembly global variables

(Not covered in detail) Maximum efficiency for a small but often used

piece of code

Page 16: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CS-280Dr. Mark L. Hornick

16

Inline assembly – calling a function

void main()

{

...

__asm(“rcall sub1");

// Call routine without

// a C interface

...

}

Page 17: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CS-280Dr. Mark L. Hornick

17

extern variables

extern – The definition and label for something… are external (present in another module) will be resolved by the linker

extern modifies a declaration Examples

Variables – stored in another module Functions – implemented in another module

Page 18: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

CS-280Dr. Mark L. Hornick

18

Accessing an assembly variable from C

Assembly .section .data

.global counter

counter: .word 0x1234 C++

extern int counter;

int main()

{

counter++;

}

Page 19: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

The volatile keyword

When a variable is declared volatile, the compiler will always ensure that an up-to-date value of that variable is manipulated whenever that variable is accesses.

CS-280Dr. Mark L. Hornick

19

Page 20: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

Code generated without global variable y declared volatile

int fun1() {

y=y+3;

DDRB = 0xFF;

PORTB = 0x00;

return y;

}

CS-280Dr. Mark L. Hornick

20

000000be <fun1>:

be: 80 91 60 00 lds r24, 0x0060

c2: 90 91 61 00 lds r25, 0x0061

c6: 03 96 adiw r24, 0x03 ; 3

c8: 90 93 61 00 sts 0x0061, r25

cc: 80 93 60 00 sts 0x0060, r24

d0: 2f ef ldi r18, 0xFF ; 255

d2: 27 bb out 0x17, r18 ; 23

d4: 18 ba out 0x18, r1 ; 24

d6: 08 95 ret

Page 21: CE-2810 Dr. Mark L. Hornick 1 Mixing C and assembly Safety goggles on!

Code generated with global variable y declared volatile

int fun1() {

y=y+3;

DDRB = 0xFF;

PORTB = 0x00;

return y;

}

CS-280Dr. Mark L. Hornick

21

000000be <fun1>:

be: 80 91 60 00 lds r24, 0x0060

c2: 90 91 61 00 lds r25, 0x0061

c6: 03 96 adiw r24, 0x03 ; 3

c8: 90 93 61 00 sts 0x0061, r25

cc: 80 93 60 00 sts 0x0060, r24

d0: 2f ef ldi r18, 0xFF ; 255

d2: 27 bb out 0x17, r18 ; 23

d4: 18 ba out 0x18, r1 ; 24

d6: 80 91 60 00 lds r24, 0x0060

da: 90 91 61 00 lds r25, 0x0061

de: 08 95 ret