1 / 31

Help for Lab. 1 Subroutines calling Subroutines

Help for Lab. 1 Subroutines calling Subroutines. File “interruptservice.cpp” extern volatile boolean mute_on; extern volatile boolean cause_gargle; extern volatile int gargle_on; void Process_DataASM(void); EX_INTERRUPT_HANDLER(Sport0_RX_ISR) { …….. /// Lots of good stuff

Download Presentation

Help for Lab. 1 Subroutines calling Subroutines

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Help for Lab. 1Subroutines calling Subroutines

  2. File “interruptservice.cpp” extern volatile boolean mute_on; extern volatile boolean cause_gargle; extern volatile int gargle_on; void Process_DataASM(void); EX_INTERRUPT_HANDLER(Sport0_RX_ISR) { …….. /// Lots of good stuff if (cause_gargle == TRUE) TurnGargleOnThenOff( )else gargle_on = 0; Process_DataASM( ); // Make the sound occur …….. // Lots of more good stuff; } File “interruptservice.cpp” extern volatile boolean mute_on; extern volatile boolean cause_gargle; extern volatile int gargle_on; void Process_DataASM(void); EX_INTERRUPT_HANDLER(Sport0_RX_ISR) { …….. /// Lots of good stuff Process_DataASM( ); // Make the sound occur …….. // Lots of more good stuff; } Lab 1 – Application stream WORRY ABOUT WHAT EX_INTERRUPT_HANDLER( ) MEANS IN LAB. 2

  3. Topics tackled today • Handling some “C++” keywords when programming assembly code • Programming “subroutines called by subroutines” • Programming “extern” variables • Programming “volatile” variables • Understanding what I did when • Programming “subroutines called by subroutines” • Programming “extern” variables • Programming “volatile” variables

  4. File “bloodEnglishmanASM.asm” .extern _Fee__Fv; .extern _Fi__Fv; .extern _Fo__Fv; .section program;.global _Fum__Fv; _Fum__Fv: LINK 16;CALL _Fee __Fv; CALL _Fi __Fv; CALL _Fo__Fv; P0 = [FP +4]; UNLINK; _Fum__Fv.END: JUMP (P0); File “bloodEnglishmanCPP.cpp” void Fee(void); void Fi(void); void Fo(void); void Fum(void); void Fum(void) { Fee( ); Fi( ); Fo( ); } Subroutine calling subroutineAll void functions

  5. What nursery rhyme? • Fe, • Fi, • Fo, • Fum, • I smell the blood of an Englishman?

  6. File “bloodEnglishmanASM.asm” .extern _Fee__Fi; .extern _Fi__Fi; .extern _Fo__Fi; .section program;.global _Fum__Fi; _Fum__Fi: // value passed in R0 LINK 16; R0 += 6; // pass parameter in R0 // R0 is dead – value is no longer needed CALL _Fee __Fi; R0 = 7; // pass parameter in R0 CALL _Fi __Fi; R0 = 8; // pass parameter in R0 CALL _Fo__Fi; P0 = [FP +4]; UNLINK; _Fum__Fi.END: JUMP (P0); File “bloodEnglishmanCPP.cpp” void Fee(int); void Fi(int); void Fo(int); void Fum(int); void Fum(int value) { Fee(6 + value); Fi(7); Fo(8); } Subroutine calling subroutineAll integer functions

  7. .extern _Fee__Fi; .extern _Fi__Fi; .extern _Fo__Fi; .section program;.global _Fum__Fi; _Fum__Fi: // value passed in R0 LINK 16; R0 = 6; // pass parameter in R0 CALL _Fee __Fi; R0 = 7; // pass parameter in R0 CALL _Fi __Fi; // Problem – can’t do this R0 destroyed R0 += 8; // pass parameter in R0 CALL _Fo__Fi; P0 = [FP +4]; UNLINK; _Fum__Fi.END: JUMP (P0); File “bloodEnglishmanCPP.cpp” void Fee(int); void Fi(int); void Fo(int); void Fum(int); void Fum(int value) { Fee(6); Fi(7); Fo(8 + value); } Subroutine calling subroutineAll integer functions -- WRONG

  8. .section program;.global _Fum__Fi; _Fum__Fi: // value passed in R0 LINK (16 + 4); [FP + 20] = R0; R0 = 6; // pass parameter in R0 CALL _Fee __Fi; R0 = 7; // pass parameter in R0 CALL _Fi __Fi; R0 = [FP + 20]; // Recover R0 R0 += 8; // pass parameter in R0 CALL _Fo__Fi; P0 = [FP +4]; UNLINK; // This unlink discards 20 _Fum__Fi.END: JUMP (P0); File “bloodEnglishmanCPP.cpp” void Fee(int); void Fi(int); void Fo(int); void Fum(int); void Fum(int value) { Fee(6); Fi(7); Fo(8 + value); } Subroutine calling integer subroutineSave R0 to stack frame

  9. .section program;.global _Fum__Fi; _Fum__Fi: // value passed in R0 [--SP] = R7; // R7 always saved by other routines – SAVE before LINKR7 = R0; // Save R0 to R7 LINK 16 R0 = 6; // pass parameter in R0 CALL _Fee __Fi; R0 = 7; // pass parameter in R0 CALL _Fi __Fi; R0 = R7 // Recover R0 R0 += 8; // pass parameter in R0 CALL _Fo__Fi; P0 = [FP +4]; UNLINK; R7 = [SP++]; // Recover R7 AFTER unlink _Fum__Fi.END: JUMP (P0); File “bloodEnglishmanCPP.cpp” void Fee(int); void Fi(int); void Fo(int); void Fum(int); void Fum(int value) { Fee(6); Fi(7); Fo(8 + value); } Subroutine calling integer subroutineThe way I remember the easiest

  10. .extern _thumb;.extern _thumbPt; .section L1_cache; .global _plumb; .var _plumb[5] = {1, 2, 3, 4, 5}; .global _pointers; .var _pointers[5]; .section program; File “PutInHisThumb.cpp” extern long int thumb[10]; extern long int *thumbPt[10]; long int plumb[5] = {1, 2, 3, 4, 5}; long int *pointers[6]; long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] } long int and extern long intarrays long int * and extern long int *

  11. .extern _thumb; .section L1_cache; .global _plumb; _ .var _plumb[5] = {1, 2, 3, 4, 5}; .section program;.global _Jack__FPl; // Pointer long _Jack__FPl: // pointer passed in R0 LINK 16; P0 = R0; // Use passed value as a pointer P1.L = _thumb; P1.H = _thumb; R0 = [P1 + (2 * 4)]; // LOAD P1.L = _plumb; P1.H = _plumb; R1= [P1 + (1 * 4)]; // LOAD R0 = R0 + R1; [P0 + (3 * 4)] = R0; // STORE P0 = [FP +4]; UNLINK; _ Jack__FPl .END:: JUMP (P0); File “PutInHisThumb.cpp” extern long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] } extern long int

  12. .extern _thumb; .section L1_cache; .global _plumb[5] = {1, 2, 3, 4, 5}; .section program;.global _Jack__FPl; // Pointer long _Jack__FPl: // pointer passed in R0 LINK 16; P0 = R0; // Use passed value as a pointer // R0 is now dead – can reuse P1.L = _thumb; P1.H = _thumb; R0 = [P1 + (2 * 4)]; // LOAD P1.L = _plumb; P1.H = _plumb; R1= [P1 + (1 * 4)]; // LOAD R0 = R0 + R1; [P0 + (3 * 4)] = R0; // STORE P0 = [FP +4]; UNLINK; _Jack__FPl.END: JUMP (P0); File “PutInHisThumb.cpp” extern volatile long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] } extern volatile long int

  13. .extern _star; .extern _BlinkLight__Fv; .section program;.global _Wonderwhat__Fv; _Wonderwhat__Fv: LINK 16; P1.L = _star; P1.H = _star; R0 = [P1 + (2 * 4)]; // LOAD CC = R0 == 2; IF !CC JUMP DONE; LOOP: CALL _BlinkLight__Fv;JUMP LOOP; DONE: P0 = [FP +4]; UNLINK; _Wonderwhat__Fv .END: JUMP (P0); File “TwinkleTwinkle.cpp” extern long int star[10]; void WonderWhat(void); void BlinkLight(void); void WonderWhat(void) { while (star[2] == 2) { BlinkLight( ); } } Either star[2] == 2, or it does not If star[2] == 2 then get an infinite loopotherwise BlinkLight( ) never called extern long int – optimized code

  14. .extern _star; .extern _BlinkLight__Fv; .section program;.global _Wonderwhat__Fv; _Wonderwhat__Fv: LINK 16; P1.L = _star; P1.H = _star; LOOP: R0 = [P1 + (2 * 4)]; // KEEP LOADING CC = R0 == 2; // LOOP NEEDED IF !CC JUMP DONE; CALL _BlinkLight__Fv;JUMP LOOP; DONE: P0 = [FP +4]; UNLINK; _Wonderwhat__Fv .END: JUMP (P0); File “TwinkleTwinkle.cpp” extern volatile long int star[10]; void WonderWhat(void); void BlinkLight(void); void WonderWhat(void) { while (star[2] == 2) { BlinkLight( ); } } star[2] == 2 MAY START OFF BEING 2 But since star is “volatile” then some external action may change it. Loop needed in optimized code if “volatile” memory value GOOD IDEA – WILL NOT WORK AS P1 isdestroyed during CALL BlinkLight extern volatile long int optimized code -- WRONG

  15. .extern _star; .extern _BlinkLight__Fv; .section program;.global _Wonderwhat__Fv; _Wonderwhat__Fv: [--SP] = P5; // Save the non-volatile LINK 16; P5.L = _star; P5.H = _star; LOOP: R0 = [P5 + (2 * 4)]; // KEEP LOADING CC = R0 == 2; // LOOP NEEDED IF !CC JUMP DONE; CALL _BlinkLight__Fv;JUMP LOOP; DONE: P0 = [FP +4]; UNLINK; P5 = [SP++]; _Wonderwhat__Fv .END: JUMP (P0); File “TwinkleTwinkle.cpp” extern volatile long int star[10]; void WonderWhat(void); void BlinkLight(void); void WonderWhat(void) { while (star[2] == 2) { BlinkLight( ); } } star[2] == 2 MAY START OFF BEING 2 But since star is “volatile” then some external action may change it. Loop needed in optimized code if “volatile” memory value extern volatile long int optimized code -- CORRECT

  16. Understanding what I did • Will look at things in more detail later in class • But here are some ideas of why we did what we did

  17. LINK 16 Does all the following in one instruction [--SP] = RETS; [--SP] = FP; FP = SP; SP  SP – 16; LINK (200 + 16) Does all the following in one instruction [--SP] = RETS; [--SP] = FP; FP = SP; SP  SP – 200; (Space for an array) SP  SP – 16; LINK – what does it doA correction – Processor Programming Reference 4:17

  18. LINK 16 UNLINK Unlink does all the following in one instruction SP = FP; FP = [SP++]; RETS = [SP++]; LINK (200 + 16) UNLINK Unlink does all the following in one instruction SP = FP; FP = [SP++]; RETS = [SP++]; UNLINK – what does it do

  19. File “bloodEnglishmanASM.asm” .extern _Fee__Fv; defined elsewhere .extern _Fi__Fv; .extern _Fo__Fv; .section program;.global _Fum__Fv; _Fum__Fv: Since the other functions are coded “outside” or “external” to this file then we indicate that with the keyword .extern File “bloodEnglishmanCPP.cpp” void Fee(void); void Fi(void); void Fo(void); void Fum(void); void Fum(void) { } Subroutine calling subroutineAll void functions

  20. File “bloodEnglishmanASM.asm” .extern _Fee__Fv; .extern _Fi__Fv; .extern _Fo__Fv; .section program;.global _Fum__Fv; // Not “private” _Fum__Fv: Since we want other functions (coded “outside” or “external” to this file) to be able to use Fum( ) coded in this file we must “globalize” (tell everybody) this functions name with the keyword .global File “bloodEnglishmanCPP.cpp” void Fee(void); void Fi(void); void Fo(void); void Fum(void); void Fum(void) { } Subroutine calling subroutineAll void functions

  21. File “bloodEnglishmanASM.asm” .extern _Fee__Fv; .extern _Fi__Fv; .extern _Fo__Fv; .section program;.global _Fum__Fv; _Fum__Fv: LINK 16; // Save RETS to stackCALL _Fee __Fv; // Changes RETS CALL _Fi __Fv; // Changes RETS CALL _Fo__Fv; // Changes RETS P0 = [FP +4]; // Saved RETS into P0 UNLINK; // Saved RETS into RETS // and destroy (remove) stack frame _Fum__Fv.END: JUMP (P0); The LINK 16; operation saves this subroutine’s return address (stored in the “RETurn from Subroutine register” RETS) onto the stack. This allows the processor to use register RETS when it calls other subroutines – same was as the MIPS – different register name UNLINK restores (recovers, reads) RETS from the stack so we can exit this subroutine. Subroutine calling subroutineAll void functions

  22. Name mangle changes (Do not need to remember details in quizzes and exams – critical to get correct in labs) void Foo(void)  _Foo__Fv int Foo(void)  _Foo__Fv int Foo(int)  _Foo__Fi int Foo(long int)  _Foo__Fl int Foo(int *)  _Foo__FPi Int Foo(long int *)  _Foo_FPl Can’t overload on the basis of return value Subroutine calling subroutineAll integer functions

  23. .extern _Fee__Fi; .extern _Fi__Fi; .extern _Fo__Fi; .section program;.global _Fum__Fi; _Fum__Fi: // value passed in R0 LINK 16; // R0 is unsaved R0 = 6; // pass parameter in R0 CALL _Fee __Fi; R0 = 7; // pass parameter in R0 CALL _Fi __Fi; R0 += 8; // pass parameter in R0 – WRONG VA:LUE CALL _Fo__Fi; P0 = [FP +4]; UNLINK; _Fum__Fi.END: JUMP (P0); void Fum(int value) { Fee(6); Fi(7); Fo(8 + value); } ALWAYS pass the parameter to the subroutine in R0 – very similar to MIPS Must save the passed value (in R0), otherwise it will be destroyed when we call the other subroutines while we use R0 to pass the parameter Subroutine calling subroutineAll integer functions

  24. .section program;.global _Fum__Fi; _Fum__Fi: // value passed in R0 [--SP] = R7;// Save volatile register R7 = R0; // Save passed value LINK 16; R0 = 6; // pass parameter in R0 CALL _Fee __Fi; R0 = 7; // pass parameter in R0 CALL _Fi __Fi; R0 = R7; // Recover passed value R0 += 8; // pass parameter in R0 CALL _Fo__Fi; P0 = [FP +4]; UNLINK;R7 = [SP++]; // Recover saved volatile register _Fum__Fi.END: JUMP (P0); void Fum(int value) { Fee(6); Fi(7); Fo(8 + value); } I always save a non-volatile register (R7) onto the stack -- and then save R0 into R7. Easier to remember and optimize ALWAYS pass the parameter to the subroutine in R0 – very similar to MIPS Subroutine calling subroutineAll integer functions

  25. A project containing only the file “PutInHisThumb.cpp” will not link and run because Very common error All projects must have a main( ) in them If you receive a message – can’t link to _main – when you are doing the laboratory – then this is the problem. File “PutInHisThumb.cpp” extern long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] } This file is in a project by itself. It compiles but does not link or run! Why not?

  26. File “main.cpp” extern long int thumb[10]; externlong int plumb[5] ; long int goodboy[10]; long int Jack(long int *goodboy) int main(void) { for (int count = 0; count < 10; count++) goodboy[count] = 0; Jack(goodboy); printf(“%d\n”, goodboy[3]); } File “PutInHisThumb.cpp” extern long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] } These two files compile but does not link and run-- Why not?

  27. DECLARED IN ANOTHER FILE DECLARED IN THIS FILE File “main.cpp” extern long int thumb[10]; extern long int plumb[5] ; long int goodboy[10]; File “PutInHisThumb.cpp” extern long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} DECLARED IN ANOTHER FILE DECLARED IN ANOTHER FILE DECLARED IN THIS FILE This does not link and runWhy not? IN NO FILE HAS MEMORY SPACE BEEN SET ASIDE FOR THE “THUMB” ARRAY

  28. File “main.cpp” long int thumb[10] = {2, 4, 6, 8, 10}; extern long int plumb[5] ; long int goodboy[10]; long int Jack(long int *goodboy) int main(void) { for (int count = 0; count < 10; count++) goodboy[count] = 0; Jack(goodboy); printf(“%d\n”, goodboy[3]); } File “PutInHisThumb.cpp” extern long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] } This does link and run -- because all arrays have been given “space”

  29. .extern _star; .extern _BlinkLight__Fv; .section program;.global _Wonderwhat__Fv; _Wonderwhat__Fv: LINK 16; P0 = R0; // Use passed value as a pointer P1.L = _thumb; P1.H = _thumb; LOOP: R0 = [P1 + (2 * 4)]; // KEEP LOADING CC = R0 == 2; // LOOP NEEDED IF !CC JUMP DONE; CALL _BlinkLight__Fv;JUMP LOOP; DONE: P0 = [FP +4]; UNLINK; _Wonderwhat__Fv .END: JUMP (P0); File “TwinkleTwinkle.cpp” extern volatile long int star[10]; void WonderWhat(void); void BlinkLight(void); void WonderWhat(void) { while (star[2] == 2) { BlinkLight( ); } } star[2] == 2 MAY START OFF BEING 2 But since star is “volatile” then some external action may change it. Loop with repeated read needed in optimized code if “volatile” memory value How can something in memory change like this

  30. Example from Lab. 1 Task 4 • Lab. 1 Task 4 • There is a main routine • There is an “interrupt audio” routine. Every 1 / 40000 s the interrupt routine “interrupts” (temporarily halts) main( ),then runs itself, and then returns control to main • Interrupts run under “external control” when “something happens” • switch changes or voltage changes -- unexpected • Subroutines run under “internal control” • ONLY WHEN CALLED – NEVER UNEXPECTED

  31. File “main.cpp” volatile boolean mute_on = FALSE; long int ReadSwitches(void); int main( ) InitializeSwitches( ); InitializeAudio( );StartInterrupts( ); while (1) { int value = ReadSwitches( ); // If switch pressed // – turn off sound; if (value == 0x100) mute_on = TRUE; else mute_on = FALSE; } } File “interruptservice.cpp” extern volatile boolean mute_on; void Process_DataASM(void); EX_INTERRUPT_HANDLER(Sport0_RX_ISR) { …….. /// Lots of good stuff Process_DataASM( ); // Make the sound occur …….. // Lots of more good stuff; } void Process_DataASM(void) { if (mute_on = = FALSE) MakeTheSound( ); } Example from Lab. 1 Task 4 WORRY ABOUT WHAT EX_INTERRUPT_HANDLER( ) MEANS IN LAB. 2

More Related