Some assembly help, please ^-^

Started by
5 comments, last by RuneLancer 21 years, 5 months ago
Allright, I finally decided to get my hands dirty and take a step up from C++: inline assembly. So far, I love assembly. It isn''t exactly practical, but great fun and one heck of a nice challenge. But I''ve run into what could be a snag. At first, I thought the registers were merely temporary storage locations for data the processor''d work with. Well, eax, ebx, ecx and edx. I coded my programs to make use of them as though I were given 4 working "variables" that were each used solely to store values to later, say, apply a mathematical or binary operation on them. Then I found out they weren''t plain and simply independant variables that solely held data. General Purpose Registers AH/AL AX (EAX) Accumulator BH/BL BX (EBX) Base CH/CL CX (ECX) Counter DH/DL DX (EDX) Data Exx indicates 386+ 32 bit register My question is, is there any (important) danger to just using these to hold values as I see it fit, or should they be used in a specific way? So far, a program I wrote in inline assembly in a C++ project that does nothing more than invert a sprite''s colors works wonders. But after learning that the registers weren''t just plain work "variables", I''m wondering if it worked simply by luck or if I really CAN used all 4 registers to hold data as I see it fit...
Advertisement
When using registers - in any type of assembly - you must almost always be sure to save the current value of the registers before manipulation, and then when you''re done simply restore them afterwards. This way you leave the integrity of their contents for the calling function.

Just remember, these registers are like temporary storage (extremely fast access), but they''re used in other functions or parts of code as well.

Hope that helps...
People fear what they don''t understand, hate what they can''t conquer!
Well, juging from what the compiler compiles, the only value saved when calling a function/subprogram (ie, void Blank(void) {} ) is ebx, which is PUSH'ed on the stack when the function is called and POP'ed off afterwards. So I guess that would mean the only one with importance in other places would be that one (otherwise the compiler wouldn't simply scrap the other values when coded purely in C/C++ ^^; )

Though I've seen cases where some of these registers were used by commands that didn't even specify them anywhere as parameters (such as IDIV, which had me stumped as to how one could divide with just one value until I found out it divides eax by the specified parameter).

So that's it? I'm free to use them as I please, so long as I keep in mind the fact other stuff can use them when I call parts of my code or external functions (like the win32 api)? Yay ^-^ Thanks Bashar! :D

edit: some minor corrections

[edited by - RuneLancer on November 6, 2002 11:02:59 PM]
quote:Original post by RuneLancer
Allright, I finally decided to get my hands dirty and take a step up from C++: inline assembly.

So far, I love assembly. It isn''t exactly practical, but great fun and one heck of a nice challenge. But I''ve run into what could be a snag.

At first, I thought the registers were merely temporary storage locations for data the processor''d work with. Well, eax, ebx, ecx and edx. I coded my programs to make use of them as though I were given 4 working "variables" that were each used solely to store values to later, say, apply a mathematical or binary operation on them.

Then I found out they weren''t plain and simply independant variables that solely held data.

General Purpose Registers
AH/AL AX (EAX) Accumulator
BH/BL BX (EBX) Base
CH/CL CX (ECX) Counter
DH/DL DX (EDX) Data
Exx indicates 386+ 32 bit register

My question is, is there any (important) danger to just using these to hold values as I see it fit, or should they be used in a specific way? So far, a program I wrote in inline assembly in a C++ project that does nothing more than invert a sprite''s colors works wonders. But after learning that the registers weren''t just plain work "variables", I''m wondering if it worked simply by luck or if I really CAN used all 4 registers to hold data as I see it fit...



To answer your question correctly, YES, there could be danger in manipulating the registers if you don''t push them first. Always PUSH the registers, work with them, and once you''re done, POP them back again. Otherwise, there could be some unpredictable problems with your code. Oh and btw, ASM is pretty straight forward but it can get a bit complicated when you want time crucial code. But that''s not the point of the post. Just make sure you try to avoid the BP and SP registers.


[Cyberdrek | the last true sorcerer | Spirit Mage - mutedfaith.com]
[Cyberdrek | ]
BP and SP being the base pointer and stack pointer, right?

I don''t intend to do anything TOO complicated with asm just yet, I''ll use C/C++ when I can in cases like those. But I''m an optimization nut and like to optimize my code even in unecessary places ("AHHH! I''m using THREE WHOLE CLOCK CYCLES to initialize this variable! Must optimize..."). And in some cases, such as with a sprite library I''m working on (hence the negative sprite program I wrote, which was one of the shorter things my library could do), the faster the better. So far I absolutely love assembly. It''s a nice little challenge and allows 100% control over code.

But anyhow. So whenever I toy around with registers I have to be sure to restore them when I end whatever I was coding? Gotcha. I have a feeling this is the start of something real fun. ^-^
by convention, there are caller saved and callee saved registers. basically, when you are making a function call, you expect callee saved registers to remain intact, and caller saved registers to be potentially overwritten. caller save registers are eax, ecx and edx; callee saved are ebx, esi, edi and ebp. esp is the special case and you shouldn't mess with it.

usually al, ax, eax, edx:eax in that order are used to return values of various sizes from functions. esi and edi are often used for register variables by C compilers. if you use inline assembly, i'd expect the compiler to not use the registers you're overwriting for storing register variables.

edit, in case i wasn't clear: you can freely destroy eax, ecx and edx, and you should preserve the rest.

now if you were writing interrupt service routines (ISRs), you would've had to preserve all registers and all flags.

[edited by - niyaw on November 6, 2002 11:20:21 PM]
Yeah, I was mostly using eax, ecx and edx as the assembly output from a debug compile used them, but I decided to venture forth and use ebx at one point to try to keep something in a register to avoid fetching it uselessly. However, the assembly code before actual function code is executed and after (when the function is returned from) has a section that begins by PUSHing ebx on the stack and, once everything''s done, POPing it. I''m coding my stuff like so...

type Function(parameters...){#ifdef USE_C_CODE  [the C++ version of my function]#else  _asm  {    [the assembly version]  }#endif} 


What this does is allow me to either work with the C++ code, which is easier to modify and understand at a glance than a few hundred lines of assembly (though my asm is well-commented ) or with the assembly version. I''d use the C++ version when creating the function and making important modifications (that way I can test something I understand much faster) and when I''m done, I''ll convert it to assembly, optimize as much as I can (hehe ^-^) and then use that.

I''m not sure if this is good practice, though it certainly simplifies my task. And since calling and returning from the function preserves ebx automatically (well, at least the compiler''s compiled code does), it seems I can freely overwrite ebx without having to worry about patching things up since that''s already done for me.

Dang it, this stuff makes me so excited ^-^ 1:30 am, classes tomorrow morning, and I don''t even feel like I could sleep. Thanks for the help everyone, I have a feeling I won''t get much sleep this coming weekend :D

This topic is closed to new replies.

Advertisement