Hi,
yolan51 wrote:
So I am really confused .... is there any more way to call exit ? and why there is not only one way to do it ? And is there a better/conventional way of doing syscall ?
For calling a kernel API, (for "80x86 PC") there's about 5 choices an OS developer could choose:
- Use an exception (slowest, but "int3" is best possible option for code size)
- Use a software interrupt (second slowest)
- Use a call gate
- Use SYSENTER (not supported by older CPUs, not supported in 64-bit by AMD)
- Use SYSCALL (not supported by older CPUs, not supported in 32-bit by Intel)
Of these, Linux originally used the software interrupt (on old CPUs), and when they added support for 64-bit they decided to use SYSCALL for that. However, (as far as I know) there's also support for SYSENTER and SYSCALL in 32-bit code for more recent versions of Linux, if the CPU supports it.
Of course all this is a mess. So that software doesn't need to be compiled differently for different CPUs (with different methods of accessing the kernel's API) they also added a "virtual dynamic shared object" thing, where you call some shared code and it calls the kernel using the best method the CPU and kernel support. This has the disadvantage of adding the overhead of a normal/near call to everything. However, it's also much more future-proof, and also means that some kernel API calls that don't actually require CPL=0 can be shifted into the "virtual dynamic shared object" itself (which avoids the overhead of switching to CPL=0 and back). A typical example of this is kernel API function/s to get the current time, if you're running on a CPU where Linux can use TSC as a stable time reference.
The best possible way is for code to be compiled/optimised specifically for the specific kernel and CPU; where you could get the benefits of a "virtual dynamic shared object" thing without the "extra normal/near call" overhead; and where shorter options ("int 0x80") could be used in code that isn't executed often (to reduce code size where performance doesn't matter) and where the faster but larger options are used in code that is executed often. This requires a different approach to software - specially, you want something like "source code or byte-code that's compiled to native when installed", which most Linux systems don't do; so I doubt the best possible way will ever be supported by Linux (or will ever be viable for Linux).
yolan51 wrote:
I've read/heard that "push" move the (esp or ebp) register of eitheir +4 or -4 bytes it was confusing too.... which one is it ? ... is it +4 or -4.
The stack grows towards lower addresses; so for "push" the CPU subtracts from the stack pointer, and for "pop" the CPU adds to the stack pointer. The size depends on which CPU mode and what you're pushing/popping.
yolan51 wrote:
My last question is about how can i make a simple debuging/printing functions, and if its doable or not. As in other language when i had difficulty to grasp what was happening in eitheir a struct or in a recursive loop i used print to figure out what was happening, by printing eitheir the adresses value or the value in the variable, then I could figure out things by myself I guess.
It's extremely likely that you can make simple debugging/printing functions (e.g. after learning more, if necessary). The real questions are how much you still need to learn about assembly language, how much you need to learn about the algorithms you'd want to use, and how much you'd need to learn about the environment your code would be executed in. All of these things depend on how much you already know, which is information I don't have.
Cheers,
Brendan