I looked at some compiler output, and when a function is called, it usually starts to configure the call stack like this:
PUSH EBP
MOV EBP, ESP
PUSH EDI
PUSH ESI
PUSH EBX
So, we save the base pointer of the calling routine on the stack, move our own base pointer up, and then save the contents of several registers on the stack. Then they return to their original values at the end of the procedure, for example:
LEA ESP, [EBP-0Ch]
POP EBX
POP ESI
POP EDI
POP EBP
RET
So far so good. However, I noticed that in one routine, the code that sets up the call stack looks a bit different. Actually it looks like this:
IN AL, DX
PUSH EDI
PUSH ESI
PUSH EBX
This is quite confusing for a number of reasons. First, the end-of-code code is identical to the above for the other method, and in particular, it is expected that a stored copy of EBP will be available on the stack.
, , IN AL, DX AL, EAX, , ,
XOR EAX, EAX
, .
: , , . , IN AL, DX, EC, PUSH EBP MOV EBP, ESP
55 88 EC. ? - , ?
- , CLR JIT, Visual Studio. #:
class C {
string s = "";
public void f(string s) {
this.s = s;
}
}
, , ; , , IN AL, DX, PUSH EBP, MOV EBP, ESP.
EDIT: - , IN AL, DX (opcode EC), 55 88. , , . ( , !)