2 questions acout hardware stack
2 questions acout hardware stack
1. When i pass arguments on stack to a function, wich contain values i use as counters for loops, whats better, copy them, or modify directly on stack?
I ask this questions, because i dont want to break anything used for debugging, i know how painfull it is to have to copy stack of function before calling it because it modify it.
2. When allocation memory on stack, should i use enter instruction (wich is missing in 8086), rep stos (wich is avaiable on all cpus, and dword version is avaiable on all cpus supporting pmode), or sub sp,X (wich might defeat purpose of guard page if i use too big value).
I ask this questions, because i dont want to break anything used for debugging, i know how painfull it is to have to copy stack of function before calling it because it modify it.
2. When allocation memory on stack, should i use enter instruction (wich is missing in 8086), rep stos (wich is avaiable on all cpus, and dword version is avaiable on all cpus supporting pmode), or sub sp,X (wich might defeat purpose of guard page if i use too big value).
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: 2 questions acout hardware stack
1: Arguments on the stack may normally be changed by the called procedure. local variables may not. Obviously, make backups where necessary.
2: rep stos* is only useful when you want to memset a local array. If you need to probe a stack to trigger guard pages, use page-size increments. Using push ebp; mov ebp, esp; sub esp, ...; is faster than using the microcoded ENTER instruction.
Also, guard pages and having a 8086 are mutually exclusive. Why do you need to consider both?
2: rep stos* is only useful when you want to memset a local array. If you need to probe a stack to trigger guard pages, use page-size increments. Using push ebp; mov ebp, esp; sub esp, ...; is faster than using the microcoded ENTER instruction.
Also, guard pages and having a 8086 are mutually exclusive. Why do you need to consider both?
-
- Member
- Posts: 255
- Joined: Tue Jun 15, 2010 9:27 am
- Location: Flyover State, United States
- Contact:
Re: 2 questions acout hardware stack
This belongs in the General Programming forum, but I'll answer it here and then this will all get moved with it.
1. To pass arguments to a function, you push them on the stack in some predefined order and then the function you call knows which order they were pushed. As for local variables, they are allocated on the stack, but in a different manner (using a base pointer) such that it is possible to clean up the stack at the end of a function without knowing how much was allocated.
There are two main ways of cleaning the stack up when returning from a function, C calling convention and PASCAL calling convention. In both of these conventions, arguments are passed from right to left*. There are others as well.
A function declared with C convention looks like this:
And it is called like this:
In PASCAL convention, however, the function cleans up the stack:
And you call it like this:
2. I would use sub sp, xxx. rep stos has nothing to do with setting up a stack frame, and it doesn't even affect ESP. I think you can still use the bound instruction to make sure your stack isn't broken, even if you didn't use enter.
* PASCAL might have been originally the other way around but Microsoft changed it?
1. To pass arguments to a function, you push them on the stack in some predefined order and then the function you call knows which order they were pushed. As for local variables, they are allocated on the stack, but in a different manner (using a base pointer) such that it is possible to clean up the stack at the end of a function without knowing how much was allocated.
There are two main ways of cleaning the stack up when returning from a function, C calling convention and PASCAL calling convention. In both of these conventions, arguments are passed from right to left*. There are others as well.
A function declared with C convention looks like this:
Code: Select all
; void some_function(int val)
some_function:
push ebp
mov ebp, esp ; Create a stack frame
sub esp, 4 ; Allocate a single int-sized local variable
; Do things with the variable here
mov esp, ebp ; Restore the old ESP
pop ebp ; Restore the old EBP
ret
Code: Select all
push some_value
call some_function
add esp, 4 ; The caller is responsible for cleaning up pushed parameters
Code: Select all
; int PASCAL some_other_function(int val)
some_other_function:
push ebp
mov ebp, esp ; Uses the same kind of stack frame as C
; Do something
mov esp, ebp
pop ebp
ret 4 ; This adjusts ESP so the pushed argument is considered popped
Code: Select all
push some_other_value
call some_other_function
; Stack is cleaned up for us, don't have to do anything.
* PASCAL might have been originally the other way around but Microsoft changed it?
Re: 2 questions acout hardware stack
Aaaand, moved to the General Programming sub-forum.
Re: 2 questions acout hardware stack
In the C and STDCALL calling conventions, arguments are pushed from right to left. In the PASCAL calling convention they are pushed from left to right.Tosi wrote:* PASCAL might have been originally the other way around but Microsoft changed it?
In the PASCAL and STDCALL calling conventions, the stack is restored by the called function. In the C calling convention it is restored by the calling function.
There are some differences between systems. Agner Fog maintains a very good document about it: http://www.agner.org/optimize/calling_conventions.pdf.
Re: 2 questions acout hardware stack
How do i know the page size? If i want to write code easly portable between paged and nonpaged mode, page size is 0. Page size might be also 4kb, 4mb, 2mb, 1gb.If you need to probe a stack to trigger guard pages, use page-size increments.
I can of course assume 4096, but what if newest cpu would support smaller pages? Can intel/amd guarantee me that if i use max sub sp,4094 i wont skip entire page?
-
- Member
- Posts: 255
- Joined: Tue Jun 15, 2010 9:27 am
- Location: Flyover State, United States
- Contact:
Re: 2 questions acout hardware stack
What I meant is that I've seen some functions in older Windows code that are declared PASCAL but the arguments are pushed in the order of STDCALL.
Use CPUID or some similar functionality to figure out which paging extensions the CPU supports. If it doesn't support CPUID at all then it's probably good to stick with only 4kb pages.How do i know the page size? If i want to write code easly portable between paged and nonpaged mode, page size is 0. Page size might be also 4kb, 4mb, 2mb, 1gb.
I can of course assume 4096, but what if newest cpu would support smaller pages? Can intel/amd guarantee me that if i use max sub sp,4094 i wont skip entire page?
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: 2 questions acout hardware stack
Is this an exercise in pendacy, because I think the is entire problem is moot - if you want portable code, use C. If you disagree and want portable code, do not allocate large structures on the stack. If you want fast code, use per-platform conditionals.a5498828 wrote:How do i know the page size? If i want to write code easly portable between paged and nonpaged mode, page size is 0. Page size might be also 4kb, 4mb, 2mb, 1gb.If you need to probe a stack to trigger guard pages, use page-size increments.
I can of course assume 4096, but what if newest cpu would support smaller pages? Can intel/amd guarantee me that if i use max sub sp,4094 i wont skip entire page?
In your exceptional case, I recommend not using the stack
Re: 2 questions acout hardware stack
Ok, lets say i want to create extensive function, wich make use of many temporary values.In your exceptional case, I recommend not using the stack
The only thing i can think of is using stack with push/pop instructions, storing temporary data on stack. For example, when making a loop store its counter on stack, load it only for tests/changes. What is i have multiple data, and want to access oldest? i have to pop everything, or address a stack.
For example, i can divide my function into sub functions each diffrent from the other by its own stack frame. When nesting another function i need to push bp and store current sp in bp in order to address stack in predictable manner. I could also place after bp previous bp, or even multiple bps to allow accessing higher stack frames. I belive its what enter instruction does. I only imagine how hard would be to manage the code then, must have keep track of every single item on stack, when removing position i would have to alter others, ehh... But i think its the only way to avoid 'push ax' multiple times.
-
- Member
- Posts: 255
- Joined: Tue Jun 15, 2010 9:27 am
- Location: Flyover State, United States
- Contact:
Re: 2 questions acout hardware stack
If you have a function which calls another function which calls another function and so on, you don't have to worry about cleaning up the stack when you are done in each function. The prologue, which sets up the stack frame, and the epilogue, which restores the old ESP value, do that for you. Also, local variables are only necessary if you run out of registers, which can happen easily in 32-bit assembly, or if you need some kind of array or structure that doesn't fit into a single 32-bit register. The stack frame makes it easy to access local variables once you have it set up.
Here is a skeleton for a function that uses a single local variable of DWORD size:
If you still don't understand about stack frames and local variables in assembly, I would recommend learning more while sticking to a higher-level language like C In the interim.
Here is a skeleton for a function that uses a single local variable of DWORD size:
Code: Select all
local_variable_function:
push ebp
mov ebp, esp ; Set up stack frame
sub esp, 4 ; Allocate 4 bytes for local memory
; Do something that uses all the registers here
...
mov [ebp - 4], eax ; Store the value in eax in the local variable
...
mov eax, [ebp - 4] ; Restore the local variable
...
mov esp, ebp ; This restores the old ESP since EBP isn't modified
pop ebp
ret
Re: 2 questions acout hardware stack
Functions for Win16 programs were declared PASCAL. In the Win32 headers, the PASCAL macro is defined as __stdcall so existing code needed less or no modification.Tosi wrote:What I meant is that I've seen some functions in older Windows code that are declared PASCAL but the arguments are pushed in the order of STDCALL.
-
- Member
- Posts: 255
- Joined: Tue Jun 15, 2010 9:27 am
- Location: Flyover State, United States
- Contact:
Re: 2 questions acout hardware stack
Oh, I never programmed 16-bit windows so I didn't know that.
I can't help but feel some sense of respect for Intel and Microsoft for maintaining backwards compatibility for so long, even if it is only for outdated software.
I can't help but feel some sense of respect for Intel and Microsoft for maintaining backwards compatibility for so long, even if it is only for outdated software.
Re: 2 questions acout hardware stack
Some forum members would say they don't feel any respect, for the very same reasons...Tosi wrote:I can't help but feel some sense of respect for Intel and Microsoft for maintaining backwards compatibility for so long, even if it is only for outdated software.
-
- Member
- Posts: 255
- Joined: Tue Jun 15, 2010 9:27 am
- Location: Flyover State, United States
- Contact:
Re: 2 questions acout hardware stack
I don't want to be put into a position where I have to defend Microsoft, so I will retroactively make that last post sarcastic.
And I'm getting off topic.
And I'm getting off topic.