Tuesday, October 21, 2014

Displaying stack frames in ebe





It is now possible to display the current function's relevant stack data in a stack frame window in ebe.  To do this use the new frame macro in the start of a function.  For example let's suppose you want to use 3 local variables in your main function and call some function with 4 parameters.  Then you should start main like this

main:
      push   rbp
      mov    rbp, rsp
      frame  2, 3, 4   ; main has 2 parameters, will use 3 locals, and
                       ; will call functions with a maximum of 4 parameters
      sub    rsp, frame_size
 
The frame macro does not generate any instructions.  However it does determine frame_size, which could be 0 in functions with no local variables.  Ebe keeps track of the lines after the frame macro and builds a table in the stack frame window from that point forward in the code.  It will be accurate only after the subtraction of frame_size.

With Linux and OS X the frames are generally pretty simple.  Also the use of 6 register parameters means that a lot of functions will require no space on the stack for parameters to the current function or to call functions.

Here is the stack from using 2, 3, and 4 for Linux:

You can see that local1 is on the third line of the table and it addressed using [rbp-8].  Alternatively you can use simple [rbp+local1].  Let's assume you want to save the 2 parameters to main in locals 1 and 2:

      mov    [rbp+local1], rdi
      mov    [rbp+local2], rsi
 
You may have noticed the last row in the table which could have been label4.  This space is there so that the functions which you call can keep the stack on 16 byte boundaries.  The value of frame_size will always be a multiple of 16.

Now suppose you have a function which receives 9 parameters, has 2 locals and the maximum number of parameters for called functions is 5.  Then the current function will have 3 parameters on the stack.  The frame call would be

      frame  9, 2, 3

The stack frame for this function would look like this under Linux or OS X.


Here we see an empty row at the top of the table which the calling function had to prepare for.  Before making the call it placed parameters 7, 8 and 9 on the stack as shown as currPar7-9.  You can also see the addressing for parameter 7 is [rbp+16] or more simply stated as [rbp+currPar7].

Similarly you can prepare to call a function with 9 parameters from a function with 2 locals and 2 parameters using

      frame  2, 2, 9

This will generate a stack frame like this one for Linux and OS X


Again you see an empty row in the table above newPar9 so that rsp will remain a multiple of 16.  You can place values into these stack-based parameters using [rsp+newPar7].  Note that the recommendation is to use rsp for the new parameters since they are basically at positive offsets from rsp.

The main goal for ebe is to make assembly programming easier without sacrificing the main benefit from learning assembly which is to learn how the computer works.  This explains why I chose to not implement a function macro which could have generated the standard stack frame code.  If you really want it to be easier, maybe C is the answer.

I have also been working on some register re-naming tricks which can make it easier to write more complex functions, but that discussion will be for another day.

No comments: