- 博客(14)
- 收藏
- 关注
原创 IA-32e架构中的任务状态段TSS
在x86架构的发展历程中,任务状态段(Task State Segment, TSS)的角色从IA-32到IA-32e(长模式)发生了根本性转变。指令触发任务切换,CPU自动加载新任务的TSS,保存旧任务状态。此机制曾用于实现多任务操作系统,但因性能开销大,现代操作系统(如Linux/Windows)已弃用硬件任务切换。:将旧SS/RSP、EFLAGS、CS/RIP等压入新堆栈(长模式下,中断或异常发生时,即使未发生特权级的变化,也将SS/RSP压入堆栈)。:使用当前特权级对应的堆栈(如RSP0)。
2025-03-27 13:17:51
363
原创 保护模式下的任务状态段TSS
是特权级切换、中断/异常处理和任务切换的关键数据结构,但其不同字段在不同场景下的使用存在差异。现代操作系统为提升性能与灵活性,通常仅依赖TSS的栈切换功能,其余机制由软件实现。:CPU从TSS中加载目标特权级(如Ring 0)的栈指针和栈段选择子。:被自动压入新栈以保存上下文(住:压入新栈中,并非保存至TSS中)。:硬件任务切换需保存/恢复全部寄存器,效率低于软件上下文切换。:中断处理本身不依赖完整的TSS上下文,除非触发任务切换。CPU仅在特权级切换和任务切换时自动使用TSS的。
2025-03-02 23:00:00
840
原创 IA-32汇编pushad/popad指令
(Pop All General-Purpose Registers)指令虽然用于保存和恢复通用寄存器的值,但。这种设计确保了栈指针的稳定性,是x86架构栈操作安全性的重要机制。的对称性仅体现在通用寄存器的保存与恢复,在弹栈过程中被修改,破坏栈的连续性。的栈指针值,而不是压栈过程中变化的。减少4字节(32位模式下),因此。(栈指针的恢复是隐式完成的)。恢复到调用前的状态,否则后续的。增减32字节),无需手动调整。在x86架构的32位模式下,的设计保证了栈的自动平衡(会读取栈中保存的原始。
2025-03-02 15:31:56
269
原创 处理器的位数与其地址线数量的联系
决定了处理器单次能处理的数据量(如64位处理器一次可处理8字节数据)以及寄存器的最大数值范围(如32位寄存器最大存储值为 [2的32次方-1] )。64位处理器理论上支持2^{64}的寻址空间,但实际地址线数量可能因物理限制或设计需求少于64根(如48根地址线,寻址256TB)。在早期的32位处理器(如Intel 80386)中,地址线数量通常与寄存器位数一致(32根地址线,寻址4GB内存)。,32位处理器可支持36根(甚至更多)地址线,寻址64GB内存(如某些服务器CPU)。(如32位、64位)。
2025-02-25 17:28:01
358
原创 GNU C内联汇编语言的结构和用法
因为有些编译器可能定义了asm宏,双下划线是GCC的标准写法;等同于asm,但建议始终使用__asm__以避免冲突。作用:告诉编译器"这段代码有副作用,不要优化我";可以使用任意字母数字组合(但建议用有意义的名称);格式规则:“约束”(变量),多个用逗号分隔;任何影响EFLAGS的指令都要声明 "cc"如果指令修改了任意内存(非通过操作数指定的)不用,编译器会自动处理操作数涉及的寄存器;必须声明的是那些"隐藏"修改的寄存器。注意:优化可能影响可读性,需谨慎使用。输出在前,输入在后,用冒号分隔;
2025-02-14 12:33:22
1021
转载 linux内核-系统调用之参数传递
因此,当系统调用服务例程进入栈时,它会找到system_call()或sysenter_entry()的返回地址,然后是存储在ebx中的参数(系统调用的第一个参数),存储在ecx中的参数。其次,寄存器的使用使得系统调用处理程序的结构类似于其他异常处理程序的结构(通过int N指令完成的中断,并不叫中断,相反,它属于异常范畴,因为这条指令引起的中断来源于 CPU 内部而非外部)。除了在eax中传递的系统调用号之外,参数的数量不能超过6个,因为80×86处理器的寄存器数量非常有限。
2024-11-27 11:01:40
163
转载 int 15h中断获取内存信息
在启动分页机制之前,我们要设置页目录和页表信息,理论上,我们利用一页内存(4k)来存放页目录,用1k页(4M)来存放页表,可以表示4G的内存。但是我们的内存不一定就是固定4G的,可能是1G,512MB或者更小,而且除了要知道内存容量的大小,我们更想知道各段内存地址的type,因为编程时,属性为reserved的段不能被程序分配使用。基于以上问题,我们在启动分页机制之前,利用0E820h int 15h 中断获取内存信息,以便进行有效合理的设置。中断调用之后,结果存放于下列寄存器之中。
2024-11-22 17:53:41
102
原创 描述符表、段描述符选择子、段描述符与段之间的关系
当要使用一个调用门的时候,提供调用门的选择子,用于在GDT中寻找调用门的描述符,调用门的描述符提供了要调用的例程所在代码段的选择子和段内偏移,CPU会用这个例程的选择子再到GDT中寻找例程所在代码段的段描述符。,顾名思义就是存放全局段描述符的表,全局段描述符包括但不限于:操作系统内核的代码段和数据段的描述符、局部描述符表的段描述符(LDT也是段,只不过是系统段)、任务状态段TSS的段描述符、一些门的描述符。简单地讲,他们也是段。,字面意思就是存放局部段描述符的表,局部段描述符就是任务私有部分的段的描述符。
2024-11-19 11:36:40
476
转载 两张图看懂GDT、GDTR、LDT、LDTR的关系
根据描述符描述符所描述的对象不同,描述符可分为三类:储存段描述符,系统段描述符,门描述符(控制描述符)。32位汇编中16位段寄存器(CS、DS、ES、SS、FS、GS)中不再存放段基址,而 是段描述符在段描述符表中的索引值,D3-D15位是索引值,D0-D1位是优先级(RPL)用于特权检查,D2位是描述符表引用指示位TI,TI=0指 示从全局描述表GDT中读取描述符,TI=1指示从局部描述符表LDT中读取描述符。这些信息总称段选择符(段选择子)。④ 用段选择符高13位的位置索引值从LDT段中得到段描述符。
2024-10-29 18:02:56
184
原创 ld: i386 architecture of input file `kernel.o‘ is incompatible with i386:x86-64 output
学习操作系统时,链接几个用nasm汇编器生成的elf文件时,出现如题所示的错误提示。操作如下:nasm -f elf kernel.asm -o kernel.onasm -f elf string.asm -o string.onasm -f elf kliba.asm -o kliba.ogcc -c start.c -o start.o -fno-builtin-memcpyld -s -Ttext 0x30400 -o kernel.bin kernel.o kliba.o string
2021-07-05 15:18:17
2708
6
转载 内核中的内存都不分页
原文链接:https://www.cnblogs.com/james1207/p/3278424.html《linux内核设计与实现》,2.4.3节中有这么一句话:“内核中的内存都不分页”。内存分页机制是为普通进程设计的,每一个普通进程的内存空间都被划分为特定大小的页,如此一来,在某一个特定的时刻,该进程按需可以调进另一个内存页,而把长时间没有使用的页换出。内核与其它普通进程一样,也是一个进程,但却与其它普通进程不同,它可以直接操作硬件,并且它也控制着分页机制以及内存页换入换出的替换算法。因此,对内核占
2020-10-21 11:55:20
631
转载 [转载] 利用pushfd/popfd检测虚拟机(cpu模拟器)
执行popfd前:EFLAGS = 00200202[ESP] = FFFFFAFF执行popfd后:EFLAGS = 00244AD7不等于[ESP]中的FFFFFAFF,什么原因导致的呢?POPFD不是简单把[ESP]赋值给EFLAGS某些虚拟机(CPU模拟器)简单的把[ESP]值pop给了ELF,导致popfd后-》再pushfd-》再pop出来的值是相同的,实际如上,应该是不同的,popfd只对某些位有影响。这应该算是某些CPU模拟器的BUG....
2020-09-25 10:26:17
309
原创 研究X86汇编中的栈段初始化问题时候得到的一些经验
学了一段时间汇编,发现李忠老师的《X86汇编语言:从实模式到保护模式》十分不错,读下来的过程中能有一些自己的理解。栈段是个一直困扰我的问题,主要原因就是栈段不同于代码段和数据段,栈段的扩展方式是向下扩展的(向低地址扩展),所以栈段的段界限是其下限,而上限是无限制的(其实是有的,就是可用的最大的内存地址)。看过一个论坛里边,对向上同向下扩展的段的偏移地址的描述十分到位:“当段最大为1M时,在自然的...
2020-02-28 10:53:11
2605
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人