Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 228 Vote(s) - 3.46 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Why does the compiler generate this code?

#1
I disassembled an object file (most likely generated using the Visual C++ compiler) using `DumpBin` and saw the following piece of code:

... ...
mov dword ptr [ebp-4],eax // Why save EAX?
push dword ptr [ebp+14h]
push dword ptr [ebp+10h]
push dword ptr [ebp+0Ch]
push dword ptr [ebp+8]
mov eax,dword ptr [ebp-4] // Why restore EAX? Did it change at all?
call <function>
... ...

Could someone please explain why the EAX register is being saved and restored across these 4 `push` instructions?
Reply

#2
Was this built in debug mode? If so, the compiler stores every local variable on the stack so that the debugger can find them in a consistent way.

The elision of such unnecessary stores and reloads is one of the optimizations that constitutes "release" mode.
Reply

#3
Also, maybe it's compiled in release mode, but that variable has been marked as `volatile`, which tells the compiler that such variable may change without it knowing, so it is forced to continuously write/restore it on/from the stack
Reply

#4
`volatile` or not, the only _technical_ reason why `EAX` would _have to be initialized_ directly before making a function call on Windows were if that `function` is declared `__syscall`, i.e. using the Windows CS_SYSCALL calling convention. Conceptually, this is a bit similar to the UN*X x86_64 convention where `%al` contains the number of floating point type args passed in `%xmm` registers.

The syscall calling convention on Windows is identical to `__cdecl`, i.e. function args on stack in reverse order, but with the addition that `AL` contains a count of the number of arguments; this is done so that the kernel code which is usually at the final end of this knows how much data to read from the user stack onto the kernel stack to retrieve the args.

`EAX` is a scratch register for all calling conventions on 32bit Windows, its value is never preserved over function calls, initializing it directly before making a call is redundant. Even if the variable it holds were `volatile` - because a simple re-load isn't a memory barrier and doesn't "commit" a previous store. In addition, the location `[EBP - 4]` is within the _stack_, so the variable is _local_ (and a `volatile` qualifier makes little sense).

If it's not a missed optimization then it could be an invocation of a `__syscall function(...)` with different numbers of arguments, like, hypothetically,

__syscall printf_syscall_conv(char *fmt, ...);

void possibly_print_three_vals(char *fmt, int val1, int val2, int val3)
{
if (*strchr('%', fmt) == '\0') // if no "%" in fmt, pass no args
printf_syscall_conv(fmt);
else
printf_syscall_conv(fmt, val1, val2, val3);
}

This could conceivably create assembly output like yours.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through