SunQuest
           Other Programming Languages
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming Languages - MoreOther Programming Languages

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
Get inside! Sample the range of functionality easily built with JMSL Library for Time Series Data Analysis, Heat Maps, Portfolio Optimization, Monte Carlo Simulation, Stock Price Charting and more. Download Now!
  #1  
Old March 5th, 2008, 06:02 PM
brad sue brad sue is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Mar 2006
Posts: 46 brad sue User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 8 h 13 m 34 sec
Reputation Power: 3
Assembly - Local variable in subroutine

hi,
I would like to know how to return local variables from a subroutine (for HCS12 assembly). To create local variables, I know I can use the stack pointer and allocate one or two memory bytes by moving the stack up.
My problem is that I dont know how to return an extra variable.

Say, we have this problem:

I want to compare two arrays and count the number of elements that are equal in both arrays.
X register stores the address of Array1
Y register stores the address of Array2

A is used to going through the Array1 and compare.
B is the number of matches.

All registers for the microprocessor are used now!

when I leave the subroutine, I just pull all the registers used.

Is it possible to manage to have another local variable? if yes how to store it when I leave the subroutine since all registers are used?

thank you
B

Reply With Quote
  #2  
Old March 6th, 2008, 04:40 AM
Schol-R-LEA's Avatar
Schol-R-LEA Schol-R-LEA is offline
Commie Mutant Traitor
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Jun 2004
Location: The People's Republic of Berkeley
Posts: 1,082 Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level)Schol-R-LEA User rank is Lieutenant Colonel (40000 - 50000 Reputation Level) 
Time spent in forums: 3 Weeks 4 Days 10 h 21 m 50 sec
Reputation Power: 446
I found some lecture notes and a chapter from a book and another. Still one more book has large sections available which, significantly, include a section specifically on subroutines (unfortunately, important parts of that aren't in the book preview). Lastly, there is also at least one message board specific to the 68HC12, where you may get more helpful answers - most of the people here don't really know the processor.

From what is shown in the available parts of that one book, the usual approach is one pretty typical for this sort of accumulator-based CPU: basically, you do it all through the stack. This is complicated by the lack of a frame pointer, but not all that much. The main thing is to use leas to offset the stack pointer by a fixed amount to set up local space. Along with the subroutine you would use a number of equates which act as offsets from where the top of the stack will be as the function runs. These will all be set up at the start of the function, forming what is known as an activation record for the subroutine. All of the arguments and local variables will be accessed using these offsets relative to SP. You will furthermore need offsets for the stack space for any registers you save at the start of the function.You will also - and this is very important - need an offset for the 16-bit value just before the first local variable. This value will hold the return address, and you will later reset the stack to it at the end of the function.

When one subroutine calls another, it starts by pushing the values for any function arguments it is passing, as well as a space for whatever return value it will get. Note that when I say 'pushing', it doesn't necessarily use psha, pshb, etc.; if it is expedient to do so, sure, but it can also use leas and memory-to-memory copies if it is easier. But I digress.

Anyway, only after the arguments are pushed, does it bsr or jsr to the function it is calling. This does two things: it pushes the return address (the address immediately following the subroutine call instruction) onto the stack, then jumps/branches to the start of the subroutine.

Now the subroutine itself has to set up it's activation record. It starts by pushing any registers other than IP and SP which it is going to use at any point in the function, so that they don't get trashed. Then it uses leas to subtract the total size of all of the local variables to the stack, moving the top of the stack down by that much and creating the activation record. The subroutine will not use the stack again, except for calling other subroutines, until finishes. When it is finished, it uses leas again to add the size of the activation record, then pops the registers in the reverse or from which it pushed them. At that point, if you've done things right, the return value is back at the top of the stack and you can safely rts back to where you were called. The caller then has to copy the return value somewhere safe, then clean up the arguments, before going on.

Here's a simple example of what I mean (not tested code, but it should get the idea across):
Code:
; main program - note that it has to set up it's own local stack too

main_locals equ 4  ; 2 bytes for the main() locals
main_foo  equ  2    ; offset for first local 16-bit variable 
main_bar equ   0    ; offset for second local 16-bit variable
quux_ret_size equ 2      ; 16-bit return value size

main psha
       pshb
       leas -main_locals, sp  ; set up locals for main()
       ldaa 23
       staa main_foo, sp    ; set the value of foo   
       ;  do something here...
       ldab main_foo, sp    ; push foo as an argument
       leas -quux_ret_size, sp          ; make space for return value
       bsr quux            ; calling subroutine quux
       pula                  ; get return value off of stack
       leas quux_ret_size, sp         ; clear off arguments
       staa bar            ; save returned value in bar
       ; do something else
       end

;;  offsets for quux, a function that adds 17 to it argument a
;; and returns the sum
quux_locals  equ 2
quux_regs equ 2
quux_baz  equ 0
quux_retval equ 6  ; offset for the return value - locals plus regs plus size of the return address
quux_arg  equ 8  ; offset for the argument

quux psha   ; save a
       leas -quux_locals, sp ; set aside space for baz
       ldaa 23
       staa quux_baz, sp     ; initialize the value of quux_baz
       ldaa quux_arg, sp    ; get the argument value
       adda quux_baz, sp  ; add argument with baz
       staa quux_retval, sp ; ... and put it in th return value
       leas  quux_locals, sp  ; clean up locals
       pula                        ; restore registers
       rts        ; return


OK, this isn't a very sensible example, and I'm not sure if it would work, but it ought to give you an idea of how this works. You may want to compare this to the GCC approach, which is different. You may also want to see a previous posting of mine for more information - it covers a different CPU's assembly language, but the ideas are similar. HTH, comments and corrections welcome.
__________________
Rev First Speaker Schol-R-LEA;2 JAM LCF ELF KoR KCO BiWM TGIF
#define KINSEY (rand() % 7) λ Scheme is the Red Pill
Scheme in ShortUnderstanding the C/C++ Preprocessor
Taming PythonA Highly Opinionated Review of Programming Languages for the Novice, v1.1

FOR SALE: One ShapeSystem 2300 CMD, extensively modified for human use. Includes s/w for anthro, transgender, sex-appeal enhance, & Gillian Anderson and Jason D. Poit clone forms. Some wear. $4500 obo. tverres@et.ins.gov

Last edited by Schol-R-LEA : March 6th, 2008 at 04:46 AM.

Reply With Quote
  #3  
Old March 6th, 2008, 02:29 PM
brad sue brad sue is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Mar 2006
Posts: 46 brad sue User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 8 h 13 m 34 sec
Reputation Power: 3
Thank you Schol-R-LEA,
It makes more sense now.
I will read your previous post on this topic to see what is in there.
B

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming Languages - MoreOther Programming Languages > Assembly - Local variable in subroutine


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump


Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 





© 2003-2008 by Developer Shed. All rights reserved. DS Cluster 4 hosted by Hostway