Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jan 20th, 2006, 10:04 AM   #1
CodeJunkie
Programmer
 
Join Date: Aug 2005
Location: England
Posts: 37
Rep Power: 0 CodeJunkie is on a distinguished road
A noob to Assembly

I am still learning the basic fundaments of assembly so my knowledge is still extremely immature.
I keep finding myself perplexed over one detail despite extensive research, and so I feel compelled to simply ask..

my question is simply, why does assembly push a registery onto the stack before I.e calling a routine that collects a value?
I understand that it is saving the registery , but if this instruction is located at the start of the program, what is it that it is saving?
It appears to me that it is saving before it is getting the result?

I am quite confused by this, because I have never encountered it from any high level languages, (only that recursion implements the stack..)

I would really appreciate anybody taking the time to explain, thanks everybody !
CodeJunkie is offline   Reply With Quote
Old Jan 20th, 2006, 10:30 AM   #2
Lich
Professional Programmer
 
Lich's Avatar
 
Join Date: May 2005
Location: Detroit
Posts: 254
Rep Power: 4 Lich is on a distinguished road
Send a message via AIM to Lich Send a message via MSN to Lich
I think it saves to allocate space to for the result. Not 100% as i'm the definition of a asm n00b
__________________
--John Cruz
Web Developer
www.cruzweb.net
Lich is offline   Reply With Quote
Old Jan 20th, 2006, 4:18 PM   #3
CodeJunkie
Programmer
 
Join Date: Aug 2005
Location: England
Posts: 37
Rep Power: 0 CodeJunkie is on a distinguished road
Thankyou Lich,

(And may I say that your web site is a truly impressive, and genuinely artistic web site!, you are very talented!)
CodeJunkie is offline   Reply With Quote
Old Jan 20th, 2006, 6:31 PM   #4
clsk
Newbie
 
Join Date: Jan 2006
Posts: 13
Rep Power: 0 clsk is on a distinguished road
IIRC it's a requirement in C to save some (can't remember which ones ATM) registers. Meaning that when your application exits the values for those registries should be the same as when the OS gave control to your program.
clsk is offline   Reply With Quote
Old Jan 20th, 2006, 9:33 PM   #5
Mad_guy
Hobbyist Programmer
 
Mad_guy's Avatar
 
Join Date: Oct 2004
Location: Sandstorm, Techno Club
Posts: 239
Rep Power: 4 Mad_guy is on a distinguished road
Send a message via AIM to Mad_guy Send a message via MSN to Mad_guy
Quote:
Originally Posted by CodeJunkie
my question is simply, why does assembly push a registery onto the stack before I.e calling a routine that collects a value?
I understand that it is saving the registery , but if this instruction is located at the start of the program, what is it that it is saving?
It appears to me that it is saving before it is getting the result?
You are too vague. Depending on the function, values could be passed to it a lot of different ways. In higher level languages for example, calling convention is a very large factor.
__________________
os: mac os 10.5.4
revision control: git
editor: emacs

site
Mad_guy is offline   Reply With Quote
Old Jan 20th, 2006, 10:34 PM   #6
linuxpimp20
Hobbyist Programmer
 
Join Date: May 2005
Location: ma
Posts: 130
Rep Power: 4 linuxpimp20 is on a distinguished road
i always thought ti was because the stack is LIFO (last in first out) So i thought it had to pop what was ever on top of the stack off into memory so it would get saved to put something else on top of the stack to use or whatever. I don't know because i haven't played around with assembly much.
linuxpimp20 is offline   Reply With Quote
Old Jan 24th, 2006, 10:55 AM   #7
CodeJunkie
Programmer
 
Join Date: Aug 2005
Location: England
Posts: 37
Rep Power: 0 CodeJunkie is on a distinguished road
Thankyou so much for your much appreciated responses, I will research this further.
CodeJunkie is offline   Reply With Quote
Old Jan 24th, 2006, 1:21 PM   #8
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
Pushing registers onto the stack (not 'registries') is how they are saved. They are saved to prevent the following code from destroying them, since they may be in use by preceding code after the called function returns. If they aren't being destroyed (used) in the following code, there is no need to push them onto the stack for later restoration with a pop. Compiler generated code tends to use the same set of registers for each function; these are the ones it saves. Hand-written assembler code usually saves only those registers that will be used inside the function. Sometimes the entire set is saved, regardless of usage. That's a belt and suspenders approach. Some languages have the calling code clean up the stack, others have the called code clean up the stack. Some may allow either method (the aboved mentioned "calling convention" addresses this issue). If you are unclear on precisely what a stack is (and particularly the CPU-implemented stack that is often used for the purpose), post back, and I'll give a generic explanation. While implementations differ from processor to processor and language to language, the operations are highly similar.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Jan 24th, 2006, 4:34 PM   #9
CodeJunkie
Programmer
 
Join Date: Aug 2005
Location: England
Posts: 37
Rep Power: 0 CodeJunkie is on a distinguished road
Thankyou again everybody and especially to Dawei you have made things far more clearer to me.

Yes, I am indeed somewhat bemused by the stack, my current understanding is only of it being some sort of temporary memory (Possibly the L1 cache?) or scratch pad for values, but I am, like you have correctly perceived extremely vague upon its correct implementation, and would very much value your guidance.

Thankyou Dawei.
CodeJunkie is offline   Reply With Quote
Old Jan 24th, 2006, 7:32 PM   #10
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
First of all, understand that this isn't cast in concrete -- I've known microprocessors that don't implement a stack as part of their architecture. Typically, though, a micro has a register dedicated as a stack pointer (the Z8000 had more than one). This is set by the program code (even if that code is in the executive) to point to an available area of memory. Quite aside from any application's manipulation of it, it is often used directly by the processor. For instance, when an interrupt occurs, a unilateral piece of code, unconnected to the code that is currently executing, is going to be run. This will no doubt require the use of registers whose contents are important to the code that is running at the time of the interrupt.

The machine saves the address of the current instruction (or the next one to be executed, if it plans to complete the current one) by pushing it onto the stack, then saves important registers (possibly just flag states) by pushing them also. This is a built-in operation.

By a push, I mean it stores the contents of the register at the location pointed to by the stack pointer and then moves the pointer to the next available location. The majority of devices decrement the pointer, which means that the stack grows downward, toward a lower memory address. Some increment the pointer. The address of the interrupt routine is then placed in the instruction pointer, and that code is executed. Generally, it is the responsibility of the interrupt service routine to push any additional registers which it plans to use. When the interrupt service routine finishes (and it needs to be short, in real-time situations), the saved values are popped from the stack. Popping means that the value on the stack is moved back into a register, then the stack pointer is moved in the opposite direction from the push. The old execution point winds up in the instruction pointer, and execution proceeds from where it left off, with all previous register values intact.

Function call instructions also trigger this built-in process to save the current point of execution, branch to the function code, execute it, then restore the original point of execution. Often, this process does NOT save the flags register.

Many assembly language programmers and many compilers use the same stack pointer to push and pop registers when they need to be saved. Obviously, such operations must be done correctly. If they leave the stack pointer pointing to the wrong location, the return instruction (which is to restore the original point of execution) may place some improper value, possibly the contents of a variable, into the instruction pointer. The machine then runs off into the weeds and pukes on its shoes. Additionally, buffer overflows may destroy the contents of the location that is holding the return address. In that case, even if the stack pointer is correct, the same damage occurs to the shoes.

Malicious code often attempts to exploit this. Code may be put into a buffer area, the return address may be intentionally modified (by overflow) to point to this code, then, when the return instruction occurs, the instruction pointer is set to this malicious code instead of to the point of execution of the original code. One is then toast.

In addition to being used to save register contents, the stack is also often used to pass arguments to the function to be called. The calling code pushes these onto the stack PRIOR to the call (it's the code that knows what the parameter values are). When the call is made, the next instruction address goes on and the point of execution moves to the function, as described above. The parameters are on the stack, then the return address, then any registers that were saved. If the calling code is responsible for cleaning up the parameters, no biggie. When the return is made, they are on the top of the stack. The stack pointer may be moved by the amount necessary to ignore them. If the called function is responsible for cleaning them from the stack, the return address and parameters must be removed, the return address put back in readiness for the return instruction, and the return executed.

Another use is storage of local, temporary variables to be used inside the function. The stack pointer is moved an additional amount beyond its normal position to provide the amount of memory needed for these variables. The function may reference them with pointers that are set to the appropriate displacement from the stack pointer or another value keyed to it by a suitable amount. The function needs to correct for this before it returns. This correction is why you can't rely on variables local to the function being available to the calling code: they "disappear". They're there, of course, but the area becomes available for subsequent stack operations which almost certainly overwrite them with new, unrelated information.

Again, bear in mind the caveats. Pointers to arguments and locals may be set up and maintained in different ways, at the discretion of the compiler writers or the assembly language programmer. The stack pointer may be manipulated directly in lieu of being moved by a push or pop instruction. Instructions may be available that implement the storage of an entire set of registers in one swell foop. Inspection of the code emitted by the compiler will show you the methods used by your particular compiler and language if you are writing in a language such as C/C++, Fortran, or others.

This is the stack; it is not the same as static memory, nor is it the same as the heap/free store.

If you are writing in, say, C/C++, then typically, when the OS's executive launches your application, it does some preliminary work to set up some standard file handles, allocate your static memory area, some heap, and some stack. It then calls your "main", which is just another function, as far as it is concerned. Set up your "main" properly. It is supposed to return an int; define it appropriately. Some compilers will tolerate an improper definition, but it is schlocky programming to rely on that being the case.

If you are writing raw assembler programs without an OS, you'll need to set up what you need for yourself. In such cases, a detailed understanding of your machine's behavior is required.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

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

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 10:36 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC