|
-
January 12th, 2013, 01:04 AM
#14
Re: Representing and dynamically creating a managed object in assembly
BTW, another note on intuitiveness (is this really an english word? ) of assembly language source code: In the ancient times when I used that language on a regular basis, it was common practice to comment almost every single code line, and I somehow hope it still is. This is particularly useful when you're holding many values/pointers in registers and/or holding them there for long sections of code, since CPU registers lack one really useful feature of high-level language variables: descriptive names. It's also particularly useful if the human reader of the code is rather unfamiliar with the execution environment and/or concepts used
Most of my assembly code is commented, though not every line, I usually give a description of what is going on for a block of code at a time, but on some of the funky parts that are especially hard to follow I do go down to a line by line comment, and at the beggining of each routine I give a brief over all description of the routine along with a description of dedicated registers. Then I also have a few registers that are used the same in every routine, r11 allways holds the pointer to the first value passed in, r12 holds the pointer to the second, and in the routines that require 3 values......r13. r8 allways holds the pointer to the return value. rax, rdx are used for most calculations (forced to use them for certain calculations) rcx, rbx usually hold counters if needed, and rdi, rsi are the indexes into the arrays (rcx also indexes into an array for the multiplication routine). Also in all my routines I push every register used in the routine onto the stack right at the start, except rax, rcx, and rdx, the restore them right before leaving. I know that some of those are listed as volatile, but it was easier for me to expect all registers not used for passing variables to remain in tact across function calls.
All those extra registers in x64 are great, makes it scores easier to code in when you can dedicate the registers. Anyways, most of the code I put in these posts were written almost as I was writing the post. When I am stuck on something, I tend not to comment it till I get it working, or at least have a clear direction of how to proceed with it. There are times Ill spend hours trying to figure out how to make the program do what I want it to do all to pretty much erase it all when I figure it out. In fact I think the only routine that was commented was the multiply routine (thats also the only routine I WASNT working on lol).
Admittedly, it loses quite a bit of coolness that way... But a few pages down (section 3.3.2 Defining Register Types with ASSUME) I found a nice syntactic trick I wasn't even aware of during all these decades. It's possible to declare that a certain register holds a pointer to a certain struct type (which of course is the more useful the more struct field accesses you do through that register):
Im finding out why they have so many addressing modes the hard way, some modes work way better in certain situations then others. I can see where the assume directive could come in handy, and was surprised to see it used like that. I thought the assume directive was more of a debugging tool to catch the when something in the program ends in a state other than expected (like assume some part of the program is to be in such and such a state and if its not throw an error).
As far as the original purpose of this post, Ive got something working, but in order to bring it to a usefull state is going to take me some time. I am pretty much completely rewriting all the c++ code(both native and managed), but the good news is that it is starting to look as I original thought it should look. With the native c++ being the main dll and the managed side just being the wrapper. It also reminded me why I had abandond the concept. When I created an instance of the native class in the managed class, the managed object was never getting destroyed (and because the destructor was never being called the finalizer that destroys the native object was never getting called). I think its because I am using a native pointer when I should be creating my own pointer type that destroys the native object when the managed object that holds it goes out of scope.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|