Handling Arrays Completion of ideas needed for a general and complete program Final concepts needed for Final
Tackled today Review of handling external arrays from assembly code Arrays declared in another file Arrays declared in this file -- NEW Needed for arrays used by ISRs Arrays declared on the stack Pointers passed as parameters to a subroutine Can’t use arrays on the stack when used by ISR Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Example code extern short foo_startarray[40]; extern short far_finalarray[40]; void HalfWaveRectifyASM( ) { // Take the signal from foo_startarray[ ] and rectify the signal // Half wave rectify – if > 0 keep the same; if < 0 make zero // Full wave rectify – if > 0 keep the same; if < 0 then abs value // Rectify startarray[ ] and place result in finalarray[ ] for (int count = 0; count < 40; count++) { if (foo_startarray[count] < 0) far_finalarray[count] = 0; else far_finalarray[count] = foo_startarray[count]; } That we know how to code Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
What about this short foo_startarray[40]; -- Not external any more short far_finalarray[40]; -- We must put in L1_data_A void HalfWaveRectifyASM( ) { // Take the signal from foo_startarray[ ] and rectify the signal // Half wave rectify – if > 0 keep the same; if < 0 make zero // Full wave rectify – if > 0 keep the same; if < 0 then abs value // Rectify startarray[ ] and place result in finalarray[ ] for (int count = 0; count < 40; count++) { if (foo_startarray[count] < 0) far_finalarray[count] = 0; else far_finalarray[count] = foo_startarray[count]; } The program code is the same – but the data part is not Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
The program part .global _HalfWaveRectifyASM; _HalfwaveRectifyASM: .section program; .global _HalfWaveRectifyASM; _HalfwaveRectifyASM: Suggest you use this as an exercise to practice for the final Be able to demonstrate both Hardware and software loops _HalfwaveRectify.END; short foo_startarray[40]; short far_finalarray[40]; void HalfWaveRectify( ) { for (int count = 0; count < 40; count++) { if (foo_startarray[count] < 0) far_finalarray[count] = 0; else far_finalarray[count] = foo_startarray[count]; } Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
CPP array – not on the stack Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
The data part .section data1; .global _foo_startarray; The obvious .section data1; .global _foo_startarray; .global _far_finalarray Use section data1 as we are not dealing with program (instruction code) Use .global as we are declaring the array now Use .extern if the array was declared in a different file (Assembly code or in “C++) short foo_startarray[40]; short far_finalarray[40]; void HalfWaveRectify( ) { for (int count = 0; count < 40; count++) { if (foo_startarray[count] < 0) far_finalarray[count] = 0; else far_finalarray[count] = foo_startarray[count]; } THE DECLARATION IS THE EASY PART HOW ABOUT THE ARRAYS THEMSELVES Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
What we already know EXTERN STUFF NO MEMORY ALLOCATION NEEDED HERE SINCE DONE ELSE WHERE .section program We already can do Assignments 1 and 2 Labs 1, 2, 3, 4 Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Attempt 1 .section data1 Tells linker to place this stuff in memory map location data1 .align 4 We know processor works best when we start things on a boundary between groups of 4 bytes [N * 2] We need N short ints We know the processor works with address working in bytes Therefore need N * 2 bytes Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Wrong when we do simple Test – look at Blackfin Memory 20 bytes (16 bits) for N short value in C++ = N * 2 bytes Main.cpp Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Correct Approach NOT what I expected ASM Array with space for N long ints .var arrayASM[N]; ASM Array with space for N short ints var arrayASM[N / 2]; ASM Array with space for N chars var arrayASM[N / 4]; Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Quick check -- Make sure that pointers behave as expected Use Same Approach As Always EH???? Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Need to run the code to check what is happening What we expect Value 0x02CC must have some special meaning to dis-assembler Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Problem short int foo_start[N]; short int far_final[N]; extern short int foo_startASM[N]; extern short int far_finalASM[N]; extern "C" void HalfWaveASM( ); int main( ) { int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startASM[i] = i - N / 2; far_final[i] = 0; far_finalASM[i] = 0; HalfWaveASM( ); } Problem: We need a different version of HalfWaveASM( ) for every array we process Better Approach Place arrays on the stack Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Solution Problems to solve? ANSWER – Use the same techniques as you did on the MIPS! How do you PUT things on the stack? Then how do you PASS the address of something you have put onto the stack as a parameter? Then how do you USE the address of something put on the stack and passed as a parameter? extern "C" void HalfWaveASM(short int *inarray, short int *outarray ); int main( ) { short int foo_start[N]; short int far_final[N]; short int foo_startversion2[N]; short int far_finalstartversion2[N]; int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startversion2 [i] = i - N / 2; far_final[i] = 0; far_finalstartversion2 [i] = 0; HalfWaveASM(foo_start, far_final ); HalfWaveASM(foo_startversion2, finalstartversion2); } Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Last thing is the easiest to answer Then how do you USE the address of something put on the stack and passed as a parameter? Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Solution Problems to solve What do you need to put on the stack? extern "C" void HalfWaveASM(short int *inarray, short int *outarray ); int main( ) { short int foo_start[N]; short int far_final[N]; short int foo_startversion2[N]; short int far_finalstartversion2[N]; int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startversion2 [i] = i - N / 2; far_final[i] = 0; far_finalstartversion2 [i] = 0; HalfWaveASM(foo_start, far_final ); HalfWaveASM(foo_startversion2, finalstartversion2); } Problems to solve What do you need to put on the stack? We need N / 2 bytes for each array Since N = 10 that means 20 bytes 5 32 bit locations Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Solution Problems to solve What do you need to put on the stack? We need N / 2 bytes for each array Since N = 10 that means 20 bytes 5 32 bit locations So we need 20 32 bit locations for the 4 arrays PLUS we need 4 32-bit locations because we are about to call a subroutine THAT’S THAT MYSTICAL LINK 16 That’s total of 24 locations needed NOTE: CODE REVIEW -- CHECK THAT’S (20 + 4) * 4 BYTES WHEN WE WRITE CODE FOR THE MIDTERM OR FINAL extern "C" void HalfWaveASM(short int *inarray, short int *outarray ); int main( ) { short int foo_start[N]; short int far_final[N]; short int foo_startversion2[N]; short int far_finalstartversion2[N]; int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startversion2 [i] = i - N / 2; far_final[i] = 0; far_finalstartversion2 [i] = 0; HalfWaveASM(foo_start, far_final ); HalfWaveASM(foo_startversion2, finalstartversion2); } Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Undocumented solution of things placed on the stack extern "C" void HalfWaveASM(short int *inarray, short int *outarray ); int main( ) { short int foo_start[N]; short int far_final[N]; short int foo_startversion2[N]; short int far_finalstartversion2[N]; int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startversion2 [i] = i - N / 2; far_final[i] = 0; far_finalstartversion2 [i] = 0; HalfWaveASM(foo_start, far_final ); HalfWaveASM(foo_startversion2, finalstartversion2); } NO – NEED 24 * 4 Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Full Documented solution of things on the stack – Model needed in your mind extern "C" void HalfWaveASM(short int *inarray, short int *outarray ); int main( ) { short int foo_start[N]; short int far_final[N]; short int foo_startversion2[N]; short int far_finalstartversion2[N]; int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startversion2 [i] = i - N / 2; far_final[i] = 0; far_finalstartversion2 [i] = 0; HalfWaveASM(foo_start, far_final ); HalfWaveASM(foo_startversion2, finalstartversion2); } HIGH MEMORY STACK LOCATIONS (ADDRESSES) SAME IDEAS AS FOR MIPS LOWER MEMORY ADDRESSES NO NEED 24 * 4 Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
SAME IDEAS AS FOR MIPS Exam solution Step 1 HIGH MEMORY ADDRESSES extern "C" void HalfWaveASM(short int *inarray, short int *outarray ); int main( ) { short int foo_start[N]; short int far_final[N]; short int foo_startversion2[N]; short int far_finalstartversion2[N]; int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startversion2 [i] = i - N / 2; far_final[i] = 0; far_finalstartversion2 [i] = 0; HalfWaveASM(foo_start, far_final ); HalfWaveASM(foo_startversion2, finalstartversion2); } HIGH MEMORY ADDRESSES SAME IDEAS AS FOR MIPS LOWER MEMORY ADDRESSES 24 * 4 Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
SAME IDEAS AS FOR MIPS Exam solution Step 2 HIGH MEMORY ADDRESSES extern "C" void HalfWaveASM(short int *inarray, short int *outarray ); int main( ) { short int foo_start[N]; short int far_final[N]; short int foo_startversion2[N]; short int far_finalstartversion2[N]; int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startversion2 [i] = i - N / 2; far_final[i] = 0; far_finalstartversion2 [i] = 0; HalfWaveASM(foo_start, far_final ); HalfWaveASM(foo_startversion2, finalstartversion2); } HIGH MEMORY ADDRESSES SAME IDEAS AS FOR MIPS LOWER MEMORY ADDRESSES 24 * 4 Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
OK? SAME IDEAS AS FOR MIPS HIGH MEMORY ADDRESSES extern "C" void HalfWaveASM(short int *inarray, short int *outarray ); int main( ) { short int foo_start[N]; short int far_final[N]; short int foo_startversion2[N]; short int far_finalstartversion2[N]; int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startversion2 [i] = i - N / 2; far_final[i] = 0; far_finalstartversion2 [i] = 0; HalfWaveASM(foo_start, far_final ); HalfWaveASM(foo_startversion2, finalstartversion2); } HIGH MEMORY ADDRESSES LOWER MEMORY ADDRESSES SAME IDEAS AS FOR MIPS 24 * 4 Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
What we would now like to be able to do extern "C" void HalfWaveASM(short int *inarray, short int *outarray ); int main( ) { short int foo_start[N]; short int far_final[N]; short int foo_startversion2[N]; short int far_finalstartversion2[N]; int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startversion2 [i] = i - N / 2; far_final[i] = 0; far_finalstartversion2 [i] = 0; HalfWaveASM(foo_start, far_final ); HalfWaveASM(foo_startversion2, finalstartversion2); } 24 * 4 SAME IDEAS AS FOR MIPS Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Instead use in instruction This format correct? Not using SP in #define Instead use in instruction 24 * 4 extern "C" void HalfWaveASM(short int *inarray, short int *outarray ); int main( ) { short int foo_start[N]; short int far_final[N]; short int foo_startversion2[N]; short int far_finalstartversion2[N]; int i; for (i = 0; i < N; i++) foo_start[i] = i - N/2; foo_startversion2 [i] = i - N / 2; far_final[i] = 0; far_finalstartversion2 [i] = 0; HalfWaveASM(foo_start, far_final ); HalfWaveASM(foo_startversion2, finalstartversion2); } IMPROVED ONLY 1 ERROR Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Final exam version of code METHOD 1 Large offsets must be done like this R1 = LARGE_NUM R0 = R0 + R1; METHOD 2 Small offsets can be done like this R0 += SMALL_NUM Personally, I don’t want to worry about whether the number is large or small So I always use method 1 ALWAYS – AS OFTEN AS I REMEMBER 24 * 4 Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
What would happen IF we had run the code and left in my original mistake Would destroy the RETS and FP values on the stack – and the operating system would crash when main( ) exitted -- DEFECT 24 * 4 Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
How does the compiler handle things How does the compiler handle things? The same way on the stack -- different approach Compiler does LINK (24 * 4) THEN compiler uses FP (which never moves) rather than SP – which might move as new things are added to the stack Keeps additions always in the range -64 to 63 Can’t use R0 = FP; R0 +- 80; NOT SHOWN When that technique not possible, compiler uses same approach as we did I never change the SP after the link when I code to solve many (stupidity) issues Since I can count up easier than down I will use code it my way My approach also works for MC68000 and MIPS and MIPS Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019
Tackled today Review of handling external arrays from assembly code Arrays declared in another file Arrays declared in this file -- NEW Needed for arrays used by ISRs Arrays declared on the stack Pointers passed as parameters to a subroutine Can’t use arrays on the stack when used by ISR Handling Stack Arrays , Copyright M. Smith, ECE, University of Calgary, Canada 1/18/2019