Home > Blockchain >  why rsp register starts at 0x7FFFFFFFDFD0
why rsp register starts at 0x7FFFFFFFDFD0

Time:11-07

im learning x86 assembly, using the code below for testing, i see in gdb console that the rsp register which points at the top of the stack starts at 0x7FFFFFFFDFD0, if i understand correctly, in the code i haven't used push or pop which modifies rsp, so 0x7FFFFFFFDFD0 its a default value, this implicate that we have the same number of bytes in stack, but im using linux where stack size is 8mb

section .text
global _start
_start:

mov rcx, 2
add rcx, 8

mov rax, 0x1
mov rbx, 0xff
int 0x80

CodePudding user response:

For 64-bit 80x86; typically (see note 1) only 48 bits of a virtual address can be used. To make it easier to increase the number of bits that can be used in future processors without breaking older software; AMD decided that the unused highest 16 bits of a 64-bit virtual address should match. Addresses that comply with this are called "canonical addresses", and addresses that don't are called "non-canonical addresses". Normally (see note 2) any attempt to access anything at a non-canonical address causes an exception (a general protection fault).

This gives a virtual address space like:

0x0000000000000000 to 0x00007FFFFFFFFFFF = canonical (often "user space")
0x0000800000000000 to 0xFFFF7FFFFFFFFFFF = non-canonical hole
0xFFFF800000000000 to 0xFFFFFFFFFFFFFFFF = canonical (often "kernel space")

This makes it reasonably obvious that, without Address Space Layout Randomization, a process' initial thread's stack (see note 3) begins at an address slightly lower than the highest address that a process can use.

The difference between the highest address a process can use and the address you're seeing (0x7FFFFFFFDFD0) is only 2030 bytes; which (as mentioned by Fuz's comment) is used by things like ELF aux vectors, command line arguments and environment variables, that consume part of the stack before your code is started.

Note 1: Intel recently (about 2 years ago?) created an extension that (if supported by CPU and OS) makes 57 bits of a virtual address usable. In this case the "non-canonical hole" shrinks, and the highest virtual address a process can use would be increased to 0x00FFFFFFFFFFFFFF.

Note 2: More recently (about 6 months ago?) Intel created an extension that (if supported by CPU and OS and enabled for a process) can make the unused higher bits of an address ignored by the CPU; so that software can pack other information into those bits (e.g. maybe a "data type") without doing explicit masking before use.

Note 3: Because operating systems typically provide no isolation between threads (e.g. any thread can corrupt any other thread's stack or any other thread's "thread local data"); if you create more threads they can't use the same "top of stack" address.

  • Related