I am learning x86 assembly using Nasm
on Linux(Debian 12
).
I already know what is stack, so I thought when we code in assembly, we implement it ourselves.
But I saw instructions like push and pop which are meant for operations on stack. So is there a stack already implemented and ready to use? if yes, then how is it used and how can we use it. I created a strlen
function in asm
section .data
hello db "Hello World!",10,0
section .text
global _start
_start:
mov rax,hello
call strlen
mov rax,1
mov rdi,1
mov rsi,hello
syscall
mov rax,60
mov rdi,0
syscall
strlen:
mov rdx,0
strlen_loop:
cmp byte[rax],0
jz strlen_finished
inc rdx
inc rax
jmp strlen_loop
strlen_finished:
ret
This calculates the length of the string and prints it. I could use push rax
to put the value of the rax
onto the stack so that the value which was already in rax
doesn’t get lost. So we only use this already implemented stack this way or does the processor also uses this stack in some other ways? And what is the difference between this stack and the stack that we will create ourselves?
I was expecting that we ourselves had to implement the stack to keep track of the functions local variables and stuff.
2
Answers
The operating system creates a process to run an application. In that process, initially, there’s one thread, which has a working stack and stack pointer register before the first instruction in that process is run by the processor.
We don’t create the initial stack ourselves, we simply use the operating-system-provided stack to stack things — application programs do "stacking" of things but they don’t generally create/prepare those stacks for stacking. In some sense we can differentiate between the notion of using the stack (e.g. pushing & popping) and establishing some memory as a stack for a thread.
firstly when you want to execute your program in your BASH terminal, BASH will use execve syscall with the directory for your ELF file, then your linux scheduler will create task with user PID identified by the user you are using then it will allocate the stack typically 8 megabytes in linux AFAIK, then the scheduler will context switch to your program entry point by far jump, it will move the stack top to RSP before the far jump and saves your program stack because the scheduler will context switch to other processes, in IA-32 bit mode TSS play role for hardware context if your linux is using IA-32 mode it will far jump using the TSS selector in your linux loaded GDT and it will do hardware task switching by changing registers according to TSS structure loaded using LTR instruction, but in x86_64 mode TSS selector in linux used only for compatibility with 32 bit programs, because in x86_64 long mode cpu does not hardware task switching like in IA-32 mode, the scheduler software will do that.
hope this help.