我的理解是为了保护系统的整体稳定性,把程序划分为3环和0环,用户所编写的程序运行在3环内,各自拥有独立的堆栈。用户在编写代码的时候需要使用一些硬件资源,这个时候需要访问内核的接口,cpu有保护模式,所以只能通过系统调用来完成我们想执行的功能。我们大部分时候会访问glibc库中帮我们封装好的接口,在glibc封装的函数里,在需要调用真正的内核函数之前,glibc的函数会int 0x80(中断号)进行软中断,使用eax传入的系统调用号,在调用表sys_call_table上通过偏移,找到对应的函数的入口,保存3环的寄存器环境,切换到内核态,然后执行内核代码。执行结束后,把返回值保存在eax里面,然后跳到ret_from_sys_call(),完成系统调用
gdb-peda$ disassemble main
Dump of assembler code for function main:
0x000000000040114a <+0>: push rbp
0x000000000040114b <+1>: mov rbp,rsp
0x000000000040114e <+4>: sub rsp,0x10
#X64的程序,传参第一个寄存器是rdi,这里使用的是rdi的低四位(3环内)
0x0000000000401152 <+8>: mov edi,0x224
0x0000000000401157 <+13>: mov eax,0x0
0x000000000040115c <+18>: call 0x401040 <syscall@plt>
#此时rax里面是返回值,传递给了栈里面的变量
0x0000000000401161 <+23>: mov QWORD PTR [rbp-0x8],rax
0x0000000000401165 <+27>: mov rax,QWORD PTR [rbp-0x8]
#X64的程序,传参顺序%rdi, %rsi, %rdx, %rcx, %r8, %r9
#这里的rsi被赋值为系统调用的返回值
0x0000000000401169 <+31>: mov rsi,rax
#这里的0x402004指向一个地址
#arg[0]: 0x402004 --> 0x3b031b0100006425 --->后面的6425 就是%d
0x000000000040116c <+34>: mov edi,0x402004
0x0000000000401171 <+39>: mov eax,0x0
0x0000000000401176 <+44>: call 0x401030 <printf@plt>
0x000000000040117b <+49>: mov eax,0x0
0x0000000000401180 <+54>: leave
0x0000000000401181 <+55>: ret
End of assembler dump.
gdb-peda$ disassemble
Dump of assembler code for function syscall:
#这里发现内存地址跨度变换了,进入到了0环,这个把 rdi传给了rax,符合系统调用的条件
0x00007ffff7efdca0 <+0>: mov rax,rdi
0x00007ffff7efdca3 <+3>: mov rdi,rsi
0x00007ffff7efdca6 <+6>: mov rsi,rdx
0x00007ffff7efdca9 <+9>: mov rdx,rcx
0x00007ffff7efdcac <+12>: mov r10,r8
0x00007ffff7efdcaf <+15>: mov r8,r9
0x00007ffff7efdcb2 <+18>: mov r9,QWORD PTR [rsp+0x8]
0x00007ffff7efdcb7 <+23>: syscall #怀疑这里是执行系统调用的函数,但是跟不进去,不知道为什么
=> 0x00007ffff7efdcb9 <+25>: cmp rax,0xfffffffffffff001
0x00007ffff7efdcbf <+31>: jae 0x7ffff7efdcc2 <syscall+34>
0x00007ffff7efdcc1 <+33>: ret
0x00007ffff7efdcc2 <+34>: mov rcx,QWORD PTR [rip+0xbe19f] # 0x7ffff7fbbe68
0x00007ffff7efdcc9 <+41>: neg eax
0x00007ffff7efdccb <+43>: mov DWORD PTR fs:[rcx],eax
#这里应该是系统调用失败,返回一个负数
0x00007ffff7efdcce <+46>: or rax,0xffffffffffffffff
0x00007ffff7efdcd2 <+50>: ret
End of assembler dump.