It is not immediately obvious (to beginners) that "call" and "ret" use the stack. "call" stores the return address on the stack (roughly like "push return_address"/ "jmp someplace"). When you get to "ret" it gets the return address from the stack (roughly like "pop return_address" / "jmp there"). So when you get to "ret", the return address had "better" be there! If you "pushf" and don't "popf", your program tries to return to whatever address is represented by the flags... which will almost certainly segfault!
As an alternative to removing the "PUSHF" entirely, you could also pop the flags before the "ret"...
;--------------------------Procedure _print-----------------
_print:
PUSHF
MOV EAX,4 ;sys_write
MOV EBX,1 ;file descriptor 1
INT 80h ; Call Kernel
POPF ; <---
RET ; Return
I haven't tested that, but I'm pretty sure it'll work.
What Rob has shown you is how to reserve space for local variables on the stack - useful, but I don't think it's what you're asking. We can "use" the stack without "declaring" the stack (segment stack stack) because the OS does it for us. Linux works with "pages" of memory - blocks of 4096 bytes. When our program loads, Linux give us a "page" of stack (maybe more than one?). Immediately below that, Linux puts a "guard page" - a page marked "not present". If/when we try to write to that "guard page", it causes an exception. Linux sees that it's from the stack, and allocates a new page for us (and puts a new "guard page" under that). Fortunately, you don't need to understand the details of how that works to use it. You've got plenty of stack - just go ahead and use it. If you want more details, look up "virtual memory" (it's fairly complicated - a "CPU thing", not a "Nasm thing", so you won't find it in the Nasm Manual).
Best,
Frank