03 July 2009

How stack works

The stack is a special reserved area in memory for placing data.
The stack is reserved at the end of the memory area, and as data is placed on the stack, it grows downward.
The ESP register contains the memory address of the stack.

-> The PUSH, POP, CALL, RET instructions update the stack pointer indirectly.
-> Data can be placed on the stack by utilizing the ESP register as a memory pointer.
-> The stack is an important element in passing data between functions.

When the CALL instruction is executed, it places the EIP register onto the stack and then modifies the EIP register to point to the called function address. When the called function is completed, it retrieves the old EIP register value from the stack and returns control back to the original program.

The ESP register is usually copied to the EBP register at the beginning of the function.
The EBP register is used as the base pointer to the stack for all access to the stack within the function. Before returning to the calling program, the ESP register must be restored to the location pointing to the calling memory location.

function:
pushl %ebp
movl %esp, %ebp
< normal function code goes here>
movl %ebp, %esp
popl %ebp
ret

main:
push valN
push val1
call function
add [N*4], %esp




----------start cpuid.s----------
#
# cpuid.s Sample program to extract the processor Vendor ID
#

.section .data
output:
.ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"

.section .text
.globl _start

getcpuid:
pushl %ebp
movl %esp, %ebp


/* CPUID called with "EAX=0" returns the CPU's manufacturer ID
in EBX, EDX, ECX
*/
movl 8(%ebp), %eax
cpuid
movl $output, %edi
movl %ebx, 28(%edi)
movl %edx, 32(%edi)
movl %ecx, 36(%edi)

/* write(STDOUT, output, strlen(output); */
/* __NR_WRITE to %eax */
/* length of the string into %edx */
/* STDOUT into %ebx */
/* address of the string to %ecx */
movl $4, %eax
movl $1, %ebx
movl $output, %ecx
movl $42, %edx
int $0x80

movl %ebp, %esp
popl %ebp
ret


_start:
nop

/* void getcpuid(0); */
pushl $0
call getcpuid
add $4, %esp


/* exit(0); */
/* system call number into %eax */
/* return code to %ebx */
movl $1, %eax
movl $0, %ebx
int $0x80
--------------------------------------------
# as -gstabs cpuid.s -o cpuid.o
# ld cpuid.o -o cpuid
# ./cpuid
The processor Vendor ID is 'GenuineIntel'
objdump -d cpuid.o
objdump -s cpuid.o

gdb ./cpuid
gdb) break *_start+1
gdb) run
gdb) next
gdb) info registers
gdb) print/x $eax
--------------------------------------------

Reference:
Professional Assembly Language By Richard Blum

No comments:

Post a Comment