Stack and assembler
Stack and assembler
For a while i had been playing with having my variables put onto the stack, Since i'm multitasking in real mode, very soon ill need my core components to run on the stack since their values are in one place rather then one per program.
Question is, do you use the stack for variables in assembler? What calling convention do you use? Do you think its useless to, and why?
Question is, do you use the stack for variables in assembler? What calling convention do you use? Do you think its useless to, and why?
Re: Stack and assembler
Multitasking has little to do with variable scope. Are you sure you are not confused?
Multi-threading however, usually make use of local variable, which depends on ABI, can be placed on stack in most implementation.
Multi-threading however, usually make use of local variable, which depends on ABI, can be placed on stack in most implementation.
Re: Stack and assembler
Not confused, you may have misread or don't know what i'm trying to get at.
During a task switch (on my task switcher) in real mode, the stack address is saved.
On the stack, are the programs variables. (Not its global variables)
My system core is called by many programs running at once, since the variables i have now are global (physically part of the program) their content can be modified many times a second, by multiple programs calling just the one. There is many instances of the core function (open in every process that called it) but they all act off one piece of code, one set of variables but a stack for each program.
If the core function puts its variables on the stack, and there is multiple stacks (one per program) there is multiple versions of variables, off one set of code.
Understand what i mean now?
During a task switch (on my task switcher) in real mode, the stack address is saved.
On the stack, are the programs variables. (Not its global variables)
My system core is called by many programs running at once, since the variables i have now are global (physically part of the program) their content can be modified many times a second, by multiple programs calling just the one. There is many instances of the core function (open in every process that called it) but they all act off one piece of code, one set of variables but a stack for each program.
If the core function puts its variables on the stack, and there is multiple stacks (one per program) there is multiple versions of variables, off one set of code.
Understand what i mean now?
Re: Stack and assembler
There should only be one copy of a true global variable (otherwise it wouldn't be global). An example would be currentProcess or nextFreePhysicalPage. All programs need to see the same version and value of this when they access it (via the kernel). These would be stored in fixed locations in kernel memory. Some may be more indirectly stored, as part of a linked list for example, but still not on the stack.
Local variables may have the same name, but different values, for different processes. Examples would be currentDirectory or nextFreeMemoryOnHeap. These could be stored in memory that is unique to the process; in a reasonably sophisticated OS processes won't be able to see the memory belonging to other processes. Alternatively, they may be stored as part of the process structure in the process table and only accessed via the kernel.
Some variables are global to a particular process, but may not exist in other processes; for example currentLineNumber in an editor. These are best stored in the private memory of the process. Several instances of the variable may exist at the same time in the system, but only one will exist for a particular process.
Variables stored on the stack are only really useful as variables local to a particular function. Else it becomes difficult to keep track of their position. Storage in a fixed memory location is not appropriate here because functions may be called recursively or, in a multi-threaded system, different instances of the function may be active at the same time. Thus there is a need to allow several instances of the same variable within a process.
Local variables may have the same name, but different values, for different processes. Examples would be currentDirectory or nextFreeMemoryOnHeap. These could be stored in memory that is unique to the process; in a reasonably sophisticated OS processes won't be able to see the memory belonging to other processes. Alternatively, they may be stored as part of the process structure in the process table and only accessed via the kernel.
Some variables are global to a particular process, but may not exist in other processes; for example currentLineNumber in an editor. These are best stored in the private memory of the process. Several instances of the variable may exist at the same time in the system, but only one will exist for a particular process.
Variables stored on the stack are only really useful as variables local to a particular function. Else it becomes difficult to keep track of their position. Storage in a fixed memory location is not appropriate here because functions may be called recursively or, in a multi-threaded system, different instances of the function may be active at the same time. Thus there is a need to allow several instances of the same variable within a process.
Re: Stack and assembler
VolTeK wrote:Question is, do you use the stack for variables in assembler? What calling convention do you use? Do you think its useless to, and why?
iansjack wrote:There should only be one copy of a true global variable (otherwise it wouldn't be global). An example would be currentProcess or nextFreePhysicalPage. All programs need to see the same version and value of this when they access it (via the kernel). These would be stored in fixed locations in kernel memory. Some may be more indirectly stored, as part of a linked list for example, but still not on the stack.
Local variables may have the same name, but different values, for different processes. Examples would be currentDirectory or nextFreeMemoryOnHeap. These could be stored in memory that is unique to the process; in a reasonably sophisticated OS processes won't be able to see the memory belonging to other processes. Alternatively, they may be stored as part of the process structure in the process table and only accessed via the kernel.
Some variables are global to a particular process, but may not exist in other processes; for example currentLineNumber in an editor. These are best stored in the private memory of the process. Several instances of the variable may exist at the same time in the system, but only one will exist for a particular process.
Variables stored on the stack are only really useful as variables local to a particular function. Else it becomes difficult to keep track of their position. Storage in a fixed memory location is not appropriate here because functions may be called recursively or, in a multi-threaded system, different instances of the function may be active at the same time. Thus there is a need to allow several instances of the same variable within a process.
I don't give a $hit.
VolTeK wrote:My system core is called by many programs running at once, since the variables i have now are global (physically part of the program) their content can be modified many times a second, by multiple programs calling just the one. There is many instances of the core function (open in every process that called it) but they all act off one piece of code, one set of variables but a stack for each program.
If the core function puts its variables on the stack, and there is multiple stacks (one per program) there is multiple versions of variables, off one set of code.
That is how it works, in a nut shell. That is how my system will use it. I don't care about the science behind it, because i already went over it. Quit wasting your time and answer This
VolTeK wrote:Question is, do you use the stack for variables in assembler? What calling convention do you use? Do you think its useless to, and why?
I really don't know how much more straight forward i need to be with you kids.
- Kazinsal
- Member
- Posts: 559
- Joined: Wed Jul 13, 2011 7:38 pm
- Libera.chat IRC: Kazinsal
- Location: Vancouver
- Contact:
Re: Stack and assembler
That is the best way to get help from people, really. Swearing at them when they try to help you always works. /sVolTeK wrote:I don't give a $hit.
If you don't like how us "kids" handle it here (judging from your attitude I'd wager you're fifteen or so) then find someplace else. Try StackExchange. Maybe they'll cater to someone more of your brilliance and maturity.VolTeK wrote:I really don't know how much more straight forward i need to be with you kids.
Re: Stack and assembler
I guess I have better ways of spending my time than trying to help the terminally stupid. Just because you don't understand the first thing about assembler programming or OS development is no reason to be rude.
One of us knows what he is doing, the other clearly has no idea. Who's the one asking the beginner's questions? Go figure.
One of us knows what he is doing, the other clearly has no idea. Who's the one asking the beginner's questions? Go figure.
Re: Stack and assembler
I too lost interest in figure out what exactly the OP is asking; on the other hand I don't like flame. So let's keep it unresolved.
Re: Stack and assembler
Just to give you an idea about how obvious you are.
Answer: Yes I use the stack and I use the c calling convention. No, the stack is not useless.
What else could you possibly use the stack for?For a while i had been playing with having my variables put onto the stack,
Let me ponder that for a while... "my core components to run on the stack"... wtf does that mean? What are core components? The kernel(s)? And why is it running on the stack? It would make sense if it used a stack to store variables but not run on the stack. Makes no sense.Since i'm multitasking in real mode, very soon ill need my core components to run on the stack since their values are in one place rather then one per program.
Question should rather be: Do you use the stack and if you use the stack what calling convention do you use? If you think the stack is useless please explain why.Question is, do you use the stack for variables in assembler? What calling convention do you use? Do you think its useless to, and why?
Answer: Yes I use the stack and I use the c calling convention. No, the stack is not useless.
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
http://github.com/Jezze/fudge/
Re: Stack and assembler
Hi,
I do use the stack for saving/restoring "trashed" registers though.
For things called from external code (e.g. kernel API, etc); parameters are passed in registers (in order: eax for first parameter, ebx for second, etc). Returned values are returned in registers too (in the same "eax for first, ..." order) where "eax" is almost always used for status (0 = success, nonzero = some error code). Any register that is not used to return values is guaranteed to contain the same value it did before the routine was called (e.g. if a register is modified but not used to return a value, I'll push it on the stack at the start and then pop it before returning). For example:
For internal routines (routines that are only called from something else in the same piece of code) the calling convention is loosely similar; but different registers might be used for convenience (e.g. if ESI happens to be more convenient for most callers, then I'll use ESI instead of EAX for the first parameter) and status might be returned in a flag (e.g. carry flag) or no status might be returned at all. Also, if it happens to be more convenient, I might not preserve the contents of some trashed registers (and document it instead). For example:
Cheers,
Brendan
Usually, no - I use registers for temporary/local variables, and either global variables or allocated/heap for "less temporary" purposes. I do use the stack for temporary/local variables if I run out of registers, but most routines are small enough to be maintainable and therefore are small enough not to need the stack for temporary/local variables.VolTeK wrote:Question is, do you use the stack for variables in assembler?
I do use the stack for saving/restoring "trashed" registers though.
Mine.VolTeK wrote:What calling convention do you use?
For things called from external code (e.g. kernel API, etc); parameters are passed in registers (in order: eax for first parameter, ebx for second, etc). Returned values are returned in registers too (in the same "eax for first, ..." order) where "eax" is almost always used for status (0 = success, nonzero = some error code). Any register that is not used to return values is guaranteed to contain the same value it did before the routine was called (e.g. if a register is modified but not used to return a value, I'll push it on the stack at the start and then pop it before returning). For example:
Code: Select all
;Add three 32-bit unsigned values
;
;Input
; eax = first value
; ebx = second value
; ecx = third value
;
;Output
; eax = status (0 = ok, 1 = overflowed)
; ebx = result
; All other registers unchanged
addThreeValues:
add ebx,eax
jc .overflowed
add ebx,ecx
jc .overflowed
xor eax,eax
ret
.overflowed:
mov eax,1
ret
For internal routines (routines that are only called from something else in the same piece of code) the calling convention is loosely similar; but different registers might be used for convenience (e.g. if ESI happens to be more convenient for most callers, then I'll use ESI instead of EAX for the first parameter) and status might be returned in a flag (e.g. carry flag) or no status might be returned at all. Also, if it happens to be more convenient, I might not preserve the contents of some trashed registers (and document it instead). For example:
Code: Select all
;Add three 32-bit unsigned values
;
;Input
; eax = first value
; ecx = second value
; esi = third value
;
;Output
; carry = set if overflowed
; esi = result
;
;Trashed
; ecx
addThreeValues:
add ecx,eax
jc .done
add esi,ecx
.done:
ret
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Stack and assembler
To use local variables in assembler, you can do it exactly the same way as the C compiler does it.
Here is a sample of how to do it:
Here is a sample of how to do it:
Code: Select all
curr_start EQU -8
curr_size EQU -6
curr_x EQU -4
curr_y EQU -2
set_native Proc far
push ds
push es
pusha
mov bp,sp
sub sp,10
;
mov [bp].curr_x,1 ; set local variable curr_x to 1
mov [bp].curr_y,10 ; set local variable curr_y to 10
;
add sp,10
popa
pop es
pop ds
ret
set_native Endp
Re: Stack and assembler
Fasm macroses looks much less perverted than manual definition of stack offsets (although, offsets left you more optimization freedom) :
see include/macro/proc{32,64}.inc from Fasm package.
Code: Select all
; VOID ShowErrorMessage(HWND hWnd,DWORD dwError);
proc ShowErrorMessage hWnd,dwError
local lpBuffer:DWORD
lea eax,[lpBuffer]
invoke FormatMessage,FORMAT_MESSAGE_ALLOCATE_BUFFER+FORMAT_MESSAGE_FROM_SYSTEM,0,[dwError],LANG_NEUTRAL,eax,0,0
invoke MessageBox,[hWnd],[lpBuffer],NULL,MB_ICONERROR+MB_OK
invoke LocalFree,[lpBuffer]
ret
endp
-
- Member
- Posts: 255
- Joined: Tue Jun 15, 2010 9:27 am
- Location: Flyover State, United States
- Contact:
Re: Stack and assembler
I use the stack as much as possible for local variables because it's faster and makes smaller code. You also don't waste space if you want to, say, align your variable on some boundary (such as requiring dqword/16-byte alignment for faster SSE moves), and it's easy to cleanup once you're done.
This is true in both assembly and C, but more so in C because it gives the compiler more chance to alias registers, and the compiler doesn't have to worry about the variable once it's out of scope.
The manuals at http://www.agner.org/optimize/#manuals are pretty good, and they even cover the newer x86 instructions. The section you need to read is in the x86 subroutine optimization manual, section 4.2 Data Storage. I would copy the relevant text but I don't want to violate the licensing.
Essentially, using stack variables allows for more efficient use of the cache. Even if you're in real mode, if your code is running on a new processor the cache is probably enabled unless you explicitly disabled it. It also makes your code and data smaller, which is always good for real mode.
Global variables do have their place, however. If you need persistent storage of data that will exist throughout the lifetime of your program, then global variables are the way to go.
As for calling conventions, I personally prefer STDCALL, although the Microsoft name-mangling gets annoying. I still use CCALL for variadic functions though I could hack up an STDCALL snprintf if I needed to I guess. I don't use frame pointers unless I have a ton of local variables or I'm debugging and want to have a more reliable stack trace. I never liked fastcall and parameter passing in registers. If speed is that important, then I just inline the function, or if the function is too big, find a way to move it out of an inner loop, unroll the loop some, or journey to the Dark Planes to find a Blessed Scroll of Deep Wizardry Optimization.
The rest of your original post didn't make any sense, and I stopped reading the rest after I saw smoke.
This is true in both assembly and C, but more so in C because it gives the compiler more chance to alias registers, and the compiler doesn't have to worry about the variable once it's out of scope.
The manuals at http://www.agner.org/optimize/#manuals are pretty good, and they even cover the newer x86 instructions. The section you need to read is in the x86 subroutine optimization manual, section 4.2 Data Storage. I would copy the relevant text but I don't want to violate the licensing.
Essentially, using stack variables allows for more efficient use of the cache. Even if you're in real mode, if your code is running on a new processor the cache is probably enabled unless you explicitly disabled it. It also makes your code and data smaller, which is always good for real mode.
Global variables do have their place, however. If you need persistent storage of data that will exist throughout the lifetime of your program, then global variables are the way to go.
As for calling conventions, I personally prefer STDCALL, although the Microsoft name-mangling gets annoying. I still use CCALL for variadic functions though I could hack up an STDCALL snprintf if I needed to I guess. I don't use frame pointers unless I have a ton of local variables or I'm debugging and want to have a more reliable stack trace. I never liked fastcall and parameter passing in registers. If speed is that important, then I just inline the function, or if the function is too big, find a way to move it out of an inner loop, unroll the loop some, or journey to the Dark Planes to find a Blessed Scroll of Deep Wizardry Optimization.
The rest of your original post didn't make any sense, and I stopped reading the rest after I saw smoke.
Re: Stack and assembler
I love it after I tried the x86-64 ABI, I mean, when you have a lot of registers, some delicate for input and some meant to be trashed, you can totally(or greatly) avoid stack for local variables to avoid cache pollution; the result is, memory are dedicated for useful data and call/ret.Tosi wrote:I never liked fastcall and parameter passing in registers.
Re: Stack and assembler
When I write assembly routines, I do not use stack very much. Only for pushs and pops. At the beginning, I tried to maintain "x86-64 ABI 16-byte stack alignment." I gave up and now I use only "native 8-byte alignment" in the kernel. SSE instructions are not used.
I wrote my UEFI loader in assembly and I used Microsoft x64 calling convention there. I did not like the "32 bytes shadow space" requirement.
I wrote my UEFI loader in assembly and I used Microsoft x64 calling convention there. I did not like the "32 bytes shadow space" requirement.