1.2 window内核——代码跨段(Jmp和call指令对堆栈的操作)

本文详细介绍了在Windows内核中,JMP和CALL指令在代码跨段时的操作过程,包括权限检查、堆栈变化和段描述符加载。JMP指令不会影响堆栈,而CALL指令在跨段调用时涉及堆栈管理和权限切换。CALL FAR可以通过调用门实现权限提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JMP指令

jmp 0x20:0x004183D7
调用时的步骤

  1. 拆分,将0x20拆分成b0010 000,RPL=0;TI=0;index=4
  2. 查找GDT,找到第五个段描述符;四种情况可以跳转:代码段、调用门、TSS任务段、任务门
  3. 权限检查,如果是非一致代码段,要求:CPL == DPL 并且 RPL <= DPL;如果是一致代码段,要求:CPL >= DPL(CPL由CS二进制位后两位决定)
  4. 加载段描述符通过上面的权限检查后,CPU会将段描述符加载到CS段寄存器中.
  5. 代码执行CPU将 CS.Base + Offset 的值写入EIP 然后执行CS:EIP处的代码,段间跳转结束.
    如果想在跳转回来还需要用jmp指令再跳转

对于一致代码段:也就是共享的段
□ 特权级高的程序不允许访问特权级低的数据:核心态不允许访问用户态的数据
□ 特权级低的程序可以访问到特权级高的数据,但特权级不会改变:用户态还是用户态
对于普通代码段:也就是非一致代码段
□ 只允许同级访问
□ 绝对禁止不同级别的访问:核心态不是用户态,用户态也不是核心态.
JMP并不影响堆栈

1、为了对数据进行保护,普通代码段是禁止不同级别进行访问的。用户态的代码不能访问内核的数据,同样,内核态的代码也不能访问用户态的数据.

2、如果想提供一些通用的功能,而且这些功能并不会破坏内核数据,那么可以选择一致代码段,这样低级别的程序可以在不提升CPL权限等级的情况下即可以访问.
3、如果想访问普通代码段ÿ

<think>好的,我现在需要帮用户介绍JMPCALL指令的寻址方式。首先,用户之前问过输入输出指令的寻址方法,现在转向转移指令,说明他可能在学习汇编或计算机体系结构,需要理解不同指令的寻址方式。 首先,我要回忆JMPCALL指令的基本作用。JMP是无条件跳转,而CALL用于调用子程序,会保存返回地址。两者的寻址方式可能有相似之处,但CALL还需要处理返回地址的。 接下来,寻址方式有哪些呢?常见的包括立即数寻址、寄存器寻址、直接内存寻址、间接内存寻址,以及相对寻址。需要区分这些方式在JMPCALL中的应用。 比如,立即数寻址是直接在指令中给出目标地址,如JMP 0x1234。寄存器寻址则是目标地址存储在寄存器中,比如JMP EAX。直接内存寻址是跳转到某个内存地址中的值,比如JMP [0x5678]。间接可能涉及寄存器加偏移,比如JMP [EAX+4]。相对寻址是基于当前IP的偏移量,这在短跳转中常见,比如JMP SHORT label。 需要考虑不同架构的差异,比如x86ARM的区别。用户之前提到x86的例子,所以可能更关注x86架构。同时,CALL指令在跳转时会将返回地址,所以需要说明这一点对寻址的影响。 还要注意保护模式下的权限检查,比如间跳转需要检查权限描述符,这可能属于系统级的内容,但用户可能需要了解。 需要结构化回答,可能分为JMPCALL两部分,或者按寻址方式分类。之前用户的问题回答用了分点,所以保持结构清晰,用标题子标题组织内容。 需要举例子,比如汇编代码,说明不同寻址方式的具体用法。比如立即数的例子,相对偏移的例子,间接寻址的例子等。 同时,比较不同寻址方式的优缺点,比如立即数的限制,相对寻址的灵活性,间接寻址的动态性等。 可能还需要提到扩展寻址方式,比如x86的远跳转(近跳转(内),以及保护模式下的门调用等高级内容,但根据用户需求,可能需要保持基础,避免过于复杂。 最后,总结对比,帮助用户理解不同方式的应用场景,比如代码重定位使用相对寻址,动态跳转使用寄存器或间接内存寻址等。 需要确保术语准确,比如EIP、IP、RIP在x86不同模式下的使用,以及操作数大小的区别,比如16位、32位、64位模式下的不同行为。 检查是否有遗漏的寻址方式,比如基址变址寻址是否适用于JMP/CALL,或者是否有其他特定架构的寻址方式需要提及。 最后,确保用中文,使用LaTeX格式的数学符号,如寄存器名用$EAX$,地址用$0x1234$,代码块用反引号,保持回答结构清晰,帮助用户逐步理解。</think>以下是**JMP(跳转)****CALL(调用)**指令的寻址方式详解,以x86架构为例: --- ### **1. JMP指令的寻址方式** **JMP**用于无条件跳转到目标地址,其寻址方式直接影响程序执行流的切换。主要分为以下几类: #### **(1) 立即数寻址(直接跳转)** - **特点**:目标地址直接编码在指令中。 - **语法**: ```assembly JMP 0x1234 ; 跳转到绝对地址0x1234(16位模式) JMP 0x00123456 ; 跳转到绝对地址0x00123456(32位模式) ``` **地址计算**:目标地址由指令中的立即数直接给出(如$0x1234$)。 - **应用场景**:静态跳转(如固定分支)。 --- #### **(2) 寄存器寻址** - **特点**:目标地址存储在寄存器中。 - **语法**: ```assembly MOV EAX, 0x400000 JMP EAX ; 跳转到EAX中的地址 ``` **地址计算**:目标地址由寄存器值(如$EAX$)直接决定。 - **应用场景**:动态跳转(如函数指针调用)。 --- #### **(3) 内存间接寻址** - **特点**:目标地址存储在内存单元中。 - **语法**: ```assembly JMP [0x5000] ; 跳转到地址0x5000处存储的值(如[0x5000]=0x2000) JMP DWORD PTR [EBX] ; 32位模式下,跳转到EBX指向的地址 ``` **地址计算**:从内存地址中读取目标地址(如$[EBX]$)。 - **应用场景**:跳转表、多级间接跳转。 --- #### **(4) 相对寻址** - **特点**:目标地址基于当前指令指针(EIP/IP)的偏移量。 - **语法**: ```assembly JMP SHORT label ; 短跳转(-128到+127字节偏移) JMP NEAR PTR label; 近跳转(32位偏移) ``` **地址计算**:目标地址 = 当前EIP + 偏移量(如$EIP + 0x12$)。 - **应用场景**:代码重定位、条件分支(如循环)。 --- ### **2. CALL指令的寻址方式** **CALL**用于调用子程序(函数),其寻址方式与JMP类似,但需额外保存返回地址()。主要类型如下: #### **(1) 直接调用(立即数/标号)** - **特点**:目标地址直接指定。 - **语法**: ```assembly CALL 0x3000 ; 调用地址0x3000处的函数 CALL my_function ; 调用标号my_function对应的函数 ``` **地址计算**:与JMP立即数寻址相同。 --- #### **(2) 寄存器间接调用** - **特点**:目标地址存储在寄存器中。 - **语法**: ```assembly MOV EBX, my_function CALL EBX ; 调用EBX中的地址 ``` **地址计算**:寄存器值直接作为目标地址。 --- #### **(3) 内存间接调用** - **特点**:目标地址存储在内存中。 - **语法**: ```assembly CALL DWORD PTR [0x8000] ; 调用地址0x8000处存储的函数地址 CALL [EDI + 4] ; 调用EDI+4指向的函数 ``` **地址计算**:从内存中读取目标地址(如$[EDI+4]$)。 --- #### **(4) 相对调用** - **特点**:基于当前EIP的偏移量跳转。 - **语法**: ```assembly CALL NEAR PTR sub_routine ; 32位相对偏移 ``` **地址计算**:目标地址 = 当前EIP + 偏移量。 --- ### **3. 扩展寻址模式** #### **(1) 间跳转(Far JMP/CALL)** - **特点**:代码跳转(需指定选择子偏移)。 - **语法**: ```assembly JMP 0x08:0x00100000 ; 跳转到选择子0x08,偏移0x00100000 CALL FAR [EBX] ; 调用远地址(EBX指向48位地址:16位+32位偏移) ``` **地址计算**:目标地址 = 基址 + 偏移量。 - **应用场景**:操作系统内核、保护模式切换。 --- ### **4. 对比总结** | 寻址方式 | JMP示例 | CALL示例 | 特点 | |-----------------|-------------------------|-------------------------|--------------------------| | **立即数寻址** | `JMP 0x1234` | `CALL 0x3000` | 静态地址,直接编码 | | **寄存器寻址** | `JMP EAX` | `CALL EBX` | 动态跳转,灵活性高 | | **内存间接寻址**| `JMP [0x5000]` | `CALL [EDI+4]` | 支持跳转表、多级调用 | | **相对寻址** | `JMP SHORT label` | `CALL NEAR sub_routine` | 与位置无关代码(PIC)兼容 | | **间跳转** | `JMP 0x08:0x00100000` | `CALL FAR [EBX]` | 执行,保护模式专用 | --- ### **关键区别** 1. **返回地址保存**: - CALL指令自动将返回地址JMP不保存返回地址。 2. **权限检查**: - 间跳转需检查目标权限(如DPL),防止非法访问。 3. **操作数大小**: - 32位模式下默认使用32位偏移,64位模式下支持RIP相对寻址。 --- ### **实际应用** - **动态函数调用**:通过寄存器或内存间接寻址实现多态(如C++虚函数)。 - **系统调用**:CALL指令结合中断门或系统调用门(如`INT 0x80`)。 - **代码注入**:修改内存中的跳转地址(如Hook技术)。 通过灵活组合寻址方式,JMP/CALL指令可实现复杂的程序流控制,是理解程序执行逻辑的核心基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值