Is it possible to throw away a stack value?

chrstrbrts

Senior member
Aug 12, 2014
522
3
81
Hello,

What I'm really asking is in assembly is it possible to pop a value off the stack into nothing?

That is, I don't want to pop into a register or memory location; I just want to throw the value away.

Is this possible?

The motivation behind my question is in dealing with the details in returning from a called procedure.

When you call a function, that function's address is loaded into the instruction pointer register.

Also, the address of the next instruction after the call is pushed onto the stack.

When you return, the address of the next instruction is popped into the instruction pointer register.

But what if you've done scratch work in the called function that has placed values on the stack thereby obfuscating the next instruction address?

When you call return, does the processor know to pull the correct value from within the stack, or does it just pop the top value and hope that that is the correct value for the next instruction address?

If I've done scratch work in a called function that has buried the return address, I want to call 'pop into nothing' on all the top values and then call 'return' to pop the correct value into the instruction pointer.

Thanks.
 
Last edited:

Ken g6

Programming Moderator, Elite Member
Moderator
Dec 11, 1999
16,481
4,329
75
You didn't specify architecture, but assuming X86...

There's a register called "sp" (or esp or rsp). It's the Stack Pointer. pop and ret just assume it's pointing to the right place.

You can manipulate the stack pointer just like any other register. Subtract bytes to "push"; add bytes to "pop". How many bytes depends on your architecture - 32-bit, 64-bit, or something else - and how many values you want to "pop" or "push" at once.

https://stackoverflow.com/questions/17435670/how-does-the-stack-pointer-register-work
 

chrstrbrts

Senior member
Aug 12, 2014
522
3
81
You didn't specify architecture, but assuming X86...

There's a register called "sp" (or esp or rsp). It's the Stack Pointer. pop and ret just assume it's pointing to the right place.

You can manipulate the stack pointer just like any other register. Subtract bytes to "push"; add bytes to "pop". How many bytes depends on your architecture - 32-bit, 64-bit, or something else - and how many values you want to "pop" or "push" at once.

https://stackoverflow.com/questions/17435670/how-does-the-stack-pointer-register-work

Oh, I see. Instead of 'popping into nothing', just move the stack pointer to a higher address thereby ignoring the top values on the stack.

Thanks.
 

Cogman

Lifer
Sep 19, 2000
10,283
134
106
Oh, I see. Instead of 'popping into nothing', just move the stack pointer to a higher address thereby ignoring the top values on the stack.

Thanks.

Bingo. Compilers will commonly avoid using the pop instruction in favor of just adding/subtracting to the stack register as needed (in x86 land, I'm not sure about others). Further, x86 has even more special instructions like "enter" and "leave" which are completely unused by compilers because they are pointless and slow (their only benefit is that they save bytes).
 

freeskier93

Senior member
Apr 17, 2015
487
19
81
Why are you using the instruction stack for "scratch work" in the first place? Sure, you can you push/pop the instruction stack but then, as you've found out, you have to keep track of it yourself and make sure the stack is in the right place when a return is called. This kind of programming just BEGS for bugs that you'll spend forever tracking down. Just because you can do something doesn't mean you should, this is one area where assembly might give you a little to much freedom...
 
Last edited:

chrstrbrts

Senior member
Aug 12, 2014
522
3
81
Why are you using the instruction stack for "scratch work" in the first place? Sure, you can you push/pop the instruction stack but then, as you've found out, you have to keep track of it yourself and make sure the stack is in the right place when a return is called. This kind of programming just BEGS for bugs that you'll spend forever tracking down. Just because you can do something doesn't mean you should, this is one area where assembly might give you a little to much freedom...

Ah, so a better way would be to use the stack to save the state of the registers and use the registers and memory for the work that the called function does.

Then, just before returning, pop all the registers back into place.

Yes?
 

Merad

Platinum Member
May 31, 2010
2,586
19
81
On x86 the standard way to handle the call stack involves each function setting up a "stack frame" that contains all the data needed by the function call. A function has a prologue that sets up the stack frame, and an epilogue that restores the stack frame of the calling function. The ebp register stores the pointer to the base of the current function's stack frame.

A typical prologue is:

Code:
pushl %ebp  // save the calling function's frame pointer
movl %esp, %ebp  // the current stack pointer becomes our frame pointer
subl N, %esp  // N is the number of bytes we need to use on the stack

The typical epilogue is:

Code:
movl %ebp, %esp  // restore the stack state of the calling function, wipe out our stack usage
pop %ebp  // restore the calling function's frame pointer
ret // return to the caller

This pattern is so typical that there are convenience instructions to simplify your assembly code. The code below is equivalent to what I posted above:

Code:
enter N, $0

// code....

leave
ret

In practice the enter instruction isn't really used because it carries a performance penalty compared to the push/mov/sub sequence.
 

chrstrbrts

Senior member
Aug 12, 2014
522
3
81
Code:
pushl %ebp  // save the calling function's frame pointer
movl %esp, %ebp  // the current stack pointer becomes our frame pointer
subl N, %esp  // N is the number of bytes we need to use on the stack

Code:
movl %ebp, %esp  // restore the stack state of the calling function, wipe out our stack usage
pop %ebp  // restore the calling function's frame pointer
ret // return to the caller

Code:
enter N, $0

// code....

leave
ret

What kind of assembler are you using? That doesn't look like MASM or NASM
to me.

I don't recognize the use of percentage signs.

Also, it appears your source is the first operand and not the second.

Is this AT&T syntax?