ARM Assembly what is a top operation in ARM? - stack

this is my first time posting so excuse me if I'm wording my question poorly. Im taking an ARM course right now and we have the following question
"for an empty, Ascending Stack, wrtie an appropriate operation for pop, push, and top "
what is a top operation?

The top operation is the ability to check the value sitting on top of the stack. It's the value that you would get if you called pop. This operation is more commonly called "peek", so you will find quite a bit more information by googling that term instead, such as this wikipedia article:
https://en.wikipedia.org/wiki/Peek_(data_type_operation)

Related

How does Assembly Work with Stack Correctly

I always have a question about how to calculate the stretch of the stack. For example, when I have more than 8 parameters in arm64, he actually uses the area of my previous function call stack. After BL enters the function, he uses SP to add back to get the parameters, which is equivalent to crossing a stack. How can he avoid polluting the previous stack in this case? Thank you for your answer
You are correct: the function arguments which do not fit in registers will be pushed onto the stack before calling your function. Therefore, they will be at addresses with positive offsets from SP on entry to your function, and I can see why you might be concerned that it is not safe to access this memory. However, this memory is in fact "yours".
The ARM Procedure Call Standard section 6.4.2 states "A callee is permitted to modify any stack space used for receiving parameter values from the caller". So, there is no need to worry. The caller is expecting you to access this memory, and even to modify it if you want, and nothing will break if you do.

How is a context diagram different than a level 0 diagram?

What is the difference, if any, between a context diagram and a level 0 diagram?
There are some conflicts in the literature about these two terms.
Refer page 54 of this book for example. It is highly rated on google books and is a standard text in many schools. It says that a context diagram is the same as a Level 0 DFD. This one disagrees on page 210.
I'll first address the notion of "levels".
As we know, initially, the whole of the system is represented by one big block, and interactions with the system are clearly depicted. Initially, we are seeing the system with a naked eye.
Now, think of yourself holding something like a microscope. You place the lens above the system block and zoom in. This "zooming in" takes you to the next level in the hierarchy. So now, you see that the system is made up of a number of blocks.
You pick up any of the sub-blocks, and then zoom in again, thus going to the next level and so on.
So we see that there is a hierarchy of diagrams, with each level taking us to the next level of detail. The only bone of contention that now remains is name of the first level (The view with the naked eye).
As you can see, the question is not very objective, hence the ambiguity.
We can have :
Context Diagram ->
Level 0 DFD ->
-> Level n DFD</pre>
OR
Context Diagram/Level 0 DFD
->Level 1 DFD
->Level n DFD
It boils down to which one looks better. In my personal opinion , the first hierarchy is more apt. This is because initially, all we see is the system and the context within which it operates. I feel that anyone who understands the explanation should't worry much about the nomenclature.
Refer this for more.
A very difficult discussion.
My thoughts:
A context diagram only has 1 process, while a DFD level 0 can have more.
The context diagram established context at the system to be developed that is it represents the interaction at the system with various external entities.
Where data flow diagram is a simple graphical notation that can be used to represent a system in the term of input data to the system,various processing carried out on this data and the output generated by the system. It is simple to understand and use.

How to show the number of times functions are called in Instruments Time Profiler

I've tried every possible fields but can not find the number of times functions are called.
Besides, I don't get Self and # Self. What do these two numbers mean?
There are several other ways to accomplish this. One is obviously to create a static hit counter and an NSLog that emits and increments a counter. This is intrusive though and I found a way to do this with lldb.
Set a breakpoint
Execute the program until you hit the breakpoint the first time and note the breakpoint number on the right hand side of the line you hit (e.g. "Thread 1: breakpoint 7.1", note the 7.1)
Context click on the breakpoint and choose "Edit Breakpoint"
Leave condition blank and choose "Add Action"
Choose "Debugger Command"
In the command box, enter "breakpoint list 7.1" (using the breakpoint number for your breakpoint from step 2). I believe you can use "info break " if you are using gdb.
Check Options "Automatically Continue after evaluating"
Continue
Now, instead of stopping, llvm will emit info about the breakpoint including the number of times it has been passed.
As for the discussion between Glenn and Mike on the previous answer, I'll describe a performance problem where function execution count was useful: I had a particular action in my app where performance degraded considerably with each execution of the action. The Instruments time profiler showed that each time the action was executed, a particular function was taking twice as long as the time before until quickly the app would hang if the action was performed repeatedly. With the count, I was able to determine that with each execution, the function was called twice as many times as it was during the previous execution. It was then pretty easy to look for the reason, which turned out to be that someone was re-registering for a notification in NotificationCenter on each event execution. This had the effect of doubling the number of response handler calls on each execution and thus doubling the "cost" of the function each time. Knowing that it was doubling because it was called twice as many times and not because the performance was just getting worse caused me to look at the calling sequence rather than for reasons the function itself could be degrading over time.
While it's interesting, knowing the number of times called doesn't have anything to do with how much time is spent in them. Which is what Time Profiler is all about. In fact, since it does sampling, it cannot answer how many times.
It seems you cannot use Time Profiler for counting function calls. This question seems to address potential methods for counting.
W/ respect to self and #self:
Self is "The number of times the symbol calls itself." according to the Apple Docs on the Time Profiler.
From the way the numbers look though, it seems self is the summed duration of samples that had this symbol at the bottom of its stack trace. That would make:
# self: the number of samples where this symbol was at the bottom of the stack trace
% self: the percent of self samples relative to total samples of currently displayed call tree
(eg - #self / total samples).
So this wouldn't tell you how many times a method was called. But it would give you an idea how much time is spent in a method or lower in the call tree.
NOTE: I too am unsure about the various 'self' meanings though. Would love to see someone answer this authoritatively. Arrived here searching for that...
IF your objective is to find out what you need to fix to make the program as fast as possible,
Number of calls and self time may be interesting but are irrelevant.
Look at my answer to this question, in particular points 6 and 8.
EDIT: To clarify the point further, suppose the following is the timeline of execution of the program. Some of that time (in this case about 50%) is spent in an activity that can be removed, if you know what it is, such as needless buried I/O, excessive calls to new, runaway notifications, or "insignificant" data validation. If a random-time sample is taken, it has a 50% chance of occurring in that activity, and an examination of the call stack and/or program variables shows that it is doing something that can be removed. Then, if 10 such samples are taken, the activity will be seen on roughly 5 of them, regardless of whether the activity occurs in a few large chunks of time, or many small ones. The activity may be a few lines of code in a function doing something unnecessary, or it may be something much more generalized. Regardless, you recognize it, fix it, and get roughly a factor of 2 speedup. Call counts and self time contribute nothing to this process.

frame, thread, and some other jargons in ruby-debug gem, what do they mean?

I am now trying to learn ruby-debug gem, but there are many jargons I am unable to catch up. Wondering if anyone could help with the explanations?
I couldn't find them in http://bashdb.sourceforge.net/ruby-debug.html either. The author assumed we already understand them (where can I learn about them anyway?).
For example here is a result of calling help frame in rdb. I helplessly don't understand all the items I bolded.
Move the current frame to the
specified frame number.
A negative number indicates position
from the other end. So 'frame -1'
moves to the oldest frame, and 'frame
0' moves to the newest frame.
Without an argument, the command
prints the current stack frame. Since
the current position is redisplayed,
it may trigger a resyncronization if
there is a front end also watching
over things.
If a thread number is given then we
set the context for evaluating
expressions to that frame of that
thread.
It's not Ruby-specific jargon; it's common to most all debugging.
Regarding stack frames
You've likely seen stack traces:
/usr/local/rvm/gems/ree-1.8.7-2010.02/gems/redgreen-1.2.2/lib/redgreen.rb:28:in `write': Broken pipe (Errno::EPIPE)
from /usr/local/rvm/gems/ree-1.8.7-2010.02/gems/redgreen-1.2.2/lib/redgreen.rb:28:in `output_single'
from /usr/local/rvm/rubies/ree-1.8.7-2010.02/lib/ruby/1.8/test/unit/ui/console/testrunner.rb:72:in `add_fault'
from /usr/local/rvm/rubies/ree-1.8.7-2010.02/lib/ruby/1.8/test/unit/ui/console/testrunner.rb:70:in `to_proc'
from /usr/local/rvm/rubies/ree-1.8.7-2010.02/lib/ruby/1.8/test/unit/util/observable.rb:78:in `call'
The full trace shows you the "call stack". The line at the top is where the exception was thrown, and the lines under it show the path through your code that the program took to get to that point. Each of those lines is a level in the stack, called a "stack frame". So, when an exception is thrown, the current stack frame is the top of the stack. If you move to frame -1 then you're moving to the bottom of the call stack. Think of the call stack like a stack of plates. When you call a function, you add a plate to the stack, and when you return out of that function, you remove a plate from the stack. Each plate is a frame. Since you usually end up calling functions within functions within functions, you end up with fairly deep call stacks, and walking up and down them can be useful in debugging, to evaluate local variables and state at each point in the call stack.
If you'd like to read up more on call stacks, Wikipedia has a nice article.
Regarding threads
Most all modern programming languages are multi-threaded, meaning that they can execute multiple code paths (almost) concurrently. So, imagine for example that you have a visual app, and you perform some expensive computation. Your GUI won't be able to react to any user input while that computation is running, which makes the application appear to be frozen to the user. You would solve this by running two threads: One thread would be responsible for accepting and handling user input and painting the GUI, and the other thread would be responsible for doing your heavy computation. Your compute thread could be stuck in an expensive loop and your GUI thread would keep running and painting the GUI.
If you are running a multi-threaded application, then you you have to select which thread you want to evaluate your debug commands (expressions) in, since each thread will be in different points of your code, and will have different call stacks and different local variables and state and such. This is the evaluation context.
However, I noticed that this is a Rails question, and Rails is (by default) single-threaded, so you shouldn't need to worry about threads.
Chris Heald gave a really fantastic answer. A couple of very small comments. Although Ruby Rails may be single-threaded (by default), depending on which kind of web server you run Ruby/Rails the overall program (webserver + Ruby/Rails) may no longer be single-threaded.
The comment:
Since the current position is
redisplayed, it may trigger a
resyncronization if there is a front
end also watching over things.
There are some debugging front ends that parse output looking for a source-code position in the output so that the front (such as the text editor GNU/Emacs) can show you where you were you are. (For GNU/Emacs it shows this in another editor window.) When you change to a different frame, that front needs to update the display showing where you are.
Although I know this to be the case for the Emacs and the oldish debugger front end ddd, I imagine you have the same thing going on if you are debugging from vim.

Can i configure a ARM processor for Ascending Stack growth direction?

There has been one question here which talked about stack growth direction. To which Michael Burr had replied saying in ARM processors stack growth direction can be configured - i.e. either descending (normal behaviour) stack grows towards zero address (lower address) in memory or ascending, i.e. stack grows towards higher address in memory.
What is the direction of stack growth in most modern systems?
My question is: in ARM processors, how can I make the stack grow in ascending direction?
How do I configure the stack as ascending as by default it is descending? Any register bit set/reset, etc.
Well, the ARM processors don't maintain a stack directly-- but they do have instructions that are designed with that in mind: LDM and STM. So if you use STMDB at the start of a function and LDMIA at the end, you effectively have a full+descending stack: the assemblers I remember using allowed you to write "STMFD" and "LDMFD" as aliases. (A "full" stack is one where the stack pointer points to the latest word on the stack, as opposed to the next location to use)
So it's not something you can simply reconfigure at runtime: although if you were writing your own operating system with its own call convention, you could choose to use an ascending stack. Similarly, you could also choose not to use R13 as the stack pointer- that's just part of the calling convention too. This choice effectively gets embedded into the implementation of every function that uses the stack.
You have the __user_initial_stackheap() function which helps you change the SP using Stack-Start,Stack-End & heap relocation using Heap-Start,Heap-End. This function can be used during the time of the initialization since the ARM would use this to redirect Stack and Heap.
Also, you have option to use a Single-region or two-memory model[depending on your requirement]. I have used this API when I was writing UseCases which were using ARM926EJ-S.
This document was of help during my development and might be helpful to you as well.
Hope this helps.
-hjsblogger
Hmmm thumb/thumb2 might limit you to push/pop, and with thumb2 only ARMs out there I dont know that we can generically say you can go both ways. Traditional arm instructions, yes you can ldmia or ldmdb (increment after or decrement before) and stmdb and stmia. How do you make a C compiler for example climb up in addresses instead of down autmatically? Dont know.
It is like big endian on ARM, just because you can you probably dont want to because of the headaches it brings along with it.

Resources