ebp is a 32-bit general-purpose register. That was easy! :)
What makes ebp "special" is that - like esp - it defaults to using ss as its segment register.
*All* addresses on x86 involve a segment and an offset. The "rules" for interpreting the value in a segment register are completely different. In real mode, it's multiplied by 16 and added to the offset to form the complete linear address. In protected mode, the value in a segreg ("selector") serves as an index referring to a "descriptor" which, amongst other information, includes a "base" which is added to the offset to form a linear address. In any OS you're likely to encounter, the "base" is zero for all segregs ("flat memory model")(exception: fs in Windows?), so we can pretend segregs don't exist (gladly!!!)(exception: OS developers). More info here:
http://my.execpc.com/~geezer/johnfine/segments.htmOr... I understand the CPU manufacturers have Friendly Manuals...
But to get back to ebp... it's just a register, but it is "conventional" to use it as a "stack frame pointer". In 16-bit code, "[sp]" is not a valid addressing mode (!!!), so if we want to refer to items on the stack (besides push/pop), we must:
mov bp, sp
in order to reference parameters passed to the function...
mov ax, [bp + ??]
If we need some local variables - variables which exist for the duration of this function and are then "free"d...
mov bp, sp
sub sp, 2 ; just one local
mov ax, [bp + ??] ; get a parameter
shl ax, 3 ; why not?
mov [bp - 2], ax ; save it in our local var
...
mov sp, bp ; restore original sp!!!
ret
Since our caller is presumably using bp too:
our_thingie:
push bp
mov bp, sp
sub sp, bytes-of-locals
...
mov sp, bp
pop bp
ret
Now in 32-bit code, we have the option of accessing parameters/locals as [esp +/- ???], so the use of ebp might be considered "old school", but it's still convenient - keeping track of the ??? in [ebp +/- ???] tends to be easier than [esp +/- ???].
(the push ebp/mov ebp, esp/sub esp, ??? sequence is so common that the x86 architecture provides the "enter" instruction to encapsulate this. Likewise, "leave" does the mov esp, ebp/pop ebp. I do 'em the "long way" for "clarity"???)
To get back to your original question about getting command-line parameters in your program, ebp needs to concern you *only* if your program entry is "main". In that case, the "_start" label (the "real" entrypoint) is in the C startup code, and "main" is "call"ed with "int argc", "char **argv", and "char **envp" as parameters. You could access 'em as [esp + ???], but you probably want to use ebp.
If your code starts with "_start" (or some other name that you've told ld about - "-e myentry"), the argument count will be the "first" thing on the stack, "followed" (working upward) by addresses of the "args" - the first one is the name of this program, there's always at least one - "followed" (working upward) by the command line arguments, if any, "followed" by a (dword) zero, "followed" by environment variables in a similar format (zero-terminated).
If "pop"ing stuff you didn't "push" bothers you, or if the "gone forever" nature of this method bothers you, there are other ways to do it. An idea I like is:
_start:
mov [initial_esp], esp
Now, from anywhere in your program, no matter how esp/ebp have been (ab)used, you can find your command line arguments and/or environment variables with a simple calculation. You probably want to do this first anyway, so it's "just a thought"...
If you're continuing to have trouble finding your command line parameters, show us how your code starts off and how you're trying to do it...
Best,
Frank