Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Register use when calling Delphi procedure inside asm statement

Posted on 2004-08-23
11
Medium Priority
?
936 Views
Last Modified: 2011-09-20
Delphi help for register use inside asm...end statements says:
"An asm statement must preserve the EDI, ESI, ESP, EBP, and EBX registers, but can freely modify the EAX, ECX, and EDX registers."
It's easy at the first blush, but what happens when there is another procedure/function call inside asm...end bracket, e.g. as following:

procedure tobject1.method1;

  procedure nestedfunction1(argument1: integer);
  begin
    ...
  end;

  procedure inlineassembly1;
  asm
    mov eax, something // argument1
    call nestedfunction1
  end;

begin
  ...
end;

Although I do not modify any registers but eax in inlineassembly1 procedure, I cannot be sure whether nestedfunction1 inside inlineassembly1 so does or not. In this case, in order to be sure about "preserving the EDI, ESI, ESP, EBP, and EBX registers" inlineassembly1 has to look like this:

  procedure inlineassembly1;
  asm
    pushad
    mov eax, something // argument1
    call nestedfunction1
    popad
  end;
 
Since assembly routines usually are time critical solutions, the above shovn one isn't a convenient solution at all.
Moreover, I cannot see such pushad...popad brackets when disassembling compiled delphi code in CPU window. Does it mean that I needn't care of register use of Delphi procedures called inside asm...end bracket?
0
Comment
Question by:zoltan082098
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 2
11 Comments
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 11874784
I've checked... pushad and popad are visible in my own CPU window (Delphi 7) then I just add a piece of code like:

asm
  pushad
  popad
end;

And true, if something is very time-critical you might not want to call it through Assembler this way. You might want to implement this in standard Delphi code then. But in my experience asm won't give you that much increase in speed since Delphi compiles to reasonable fast binaries anyway. Only small, often-called functions do gain a performance speed through assembler...
0
 

Author Comment

by:zoltan082098
ID: 11875290
I mean "I cannot see such pushad...popad brackets when disassembling compiled delphi code in CPU window" that Delphi itself never saves the registers by pushad before calling a procedure, that is, you won't see pushad/popad pairs bracketing a procedure in a compiled delphy binary UNLESS you place them in asm...end explicitly.

BTW please trust me regarding the speed increasing in my assembler routines, they are called about several million times during the data processing. I only want to avoid the following solutions:

  asm
    ... // some assembly code here
  end;
  nestedfunction1($1234)
  asm
    ... // continuing the assembly code
  end;

Since I can better use following:

  asm
    ...
    mov eax, $1234
    call nestedfunction1
    ....
  end;

The only problem regarding this solution is:
Do I have to take care about saving and restoring all the registers before and after calling nestedfunction1? If not, which are the registers to save in this situation?

Regards,
ZOltan
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 11881041
pushad/popad would be faster in my opinion than just pushing/popping specific registers.

You must make sure EDI, ESI, ESP, EBP, and EBX don't change after calling the procedure from your ASM code but I don't think a Delphi procedure will change them. This rule would apply to ALL procedures in Delphi, not just assembler procedures. Furthermore, you must preserve those registers that you need to remember for yourself. Thus if you store some pointer in EAX, you need to push/pop it before/after calling the procedure. All other registers are those you don't need and Delphi doesn't care about them.

If a register doesn't contain any valuable info then why store it? Whatever function is calling your assembler routine, it cannot assume all registers stay unchanged. Only EDI, ESI, ESP, EBP, and EBX must be kept. All others are not important. (Unless you're returning a value, of course. Then some registers are pointing to this data.)

Advise: Just try your code without pushing/popping anything... If the code breaks, you'll have to push some registers.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 1

Expert Comment

by:aruana
ID: 11889897
Delphi assumes that nobody is suppose to play with the registers, so it need not bother to push/pop it in every call.  Imagine the overhead it will cause if need to.
Thus exist the rule,
"An asm statement must preserve the EDI, ESI, ESP, EBP, and EBX registers,..."

It means that if you are going to play with these registers, you must preserve it and pop it back upon return.  If you are sure you do not use them. Don't bother.  And you are free to play with the rest of the registers.

Now, looking back at your code,

    mov eax, something // argument1
    call nestedfunction1

following the same rule, nestedfucntion1 will not preserve EAX for you. so when it comes back, you cannot rely on its value also.
0
 

Author Comment

by:zoltan082098
ID: 11890237
Guys,
it may be about my poor English but I suspect You still not really understand what's the problem here.
My code looks like this:

asm
   
    // section 1
    ...
    // end of section 1  
   
    // section 2
    mov eax, $1234
    call nestedfunction1
    // end of section 2

    // section 3
    ...
    // end of section 3
 
end;

"An asm statement must preserve the EDI, ESI, ESP, EBP, and EBX registers,...", that is, the state of these registers must be the same BEFORE section1 and AFTER section3 respectively.

Let' say that both section1 and section3 use just eax, ecx and edx registers. Can I be sure that the EDI, ESI, ESP, EBP, and EBX registers has been preserved in this asm statement?

Of course not, because of the section2, which contains the call to nestedfunction1, and I have no clue whether a call to an ARBITRARY Delphi function/procedure applies the same rule or not, that is, to preserve the above mentioned registers.

So, there is the big question:

Do I have to save/restore these registers before/after calling an arbitrary Delphi procedure inside an asm statement or not (or, think about the worst case, wnen such Delphi procedures does contain calls to WIN32 API functions)? If so, please show me some guidelines how can I decide eaxctly WHICH registers have to be saved befor calling Delphi functions?

Regards,
Zoltan
0
 
LVL 1

Accepted Solution

by:
aruana earned 2000 total points
ID: 11899473
Delphi created the rule didn't they? They must follow the same rule.
If you do not play with those registers in section 1 and 3, you are considered as preserving them.
Then if you do not have any of your own code in nestedfunction1 that plays with the registers, you are considered as preserving them.
Any code unknown to you that does not follow this rule will screw the OS. If that happens, there is a posibility that the call would not even return back to your code.  And there is nothing you could do about it.  
So just play your part in rule and not play with the registers. Or preserve them if you do use them.
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 11941853
Aruana is correct. Delphi will preserve the same registers as the ones you're supposed to preserve. Delphi needs them internally. And actually, when you call nestedfunction1 those registers must contain correct values, the values they had when your routine was called. It will not mess up the OS, though, since the OS will just kick any bad-behaving application to the Bad-Application-Hell. (In other words: your application crashes.)

Thus, preserve those registers.
0
 
LVL 1

Expert Comment

by:aruana
ID: 11960739
"It will not mess up the OS, though, since the OS will just kick any bad-behaving application to the Bad-Application-Hell."
Well Alex, no offence, only with Windows XP, maybe.  But I still would not bet my money on it.  :-)
No offence to Microsoft either.  But that is how it is.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Suggested Courses

636 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question