汇编语句中的 jmp 与 call 指令

2024-08-25 22:52
文章标签 指令 call 语句 汇编 jmp

本文主要是介绍汇编语句中的 jmp 与 call 指令,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

jmpcall 是两条在汇编语言中非常常用的跳转指令,它们虽然都涉及程序控制流的跳转,但在功能和应用场景上有显著的区别。

1. 基本功能和行为

  • jmp 指令:

    • 功能: jmp 用于无条件跳转,直接将程序的执行流跳转到指定的地址。
    • 行为: 执行 jmp 后,程序不会记录跳转前的位置,也不会在执行完目标代码后返回。它只是简单地更改了指令指针(IP/EIP/RIP),程序从新的地址继续执行。
    • 应用场景: jmp 常用于跳转到函数的某个位置、循环控制、跳过某些代码段等。
  • call 指令:

    • 功能: call 用于调用子程序。它不仅跳转到目标地址,还保存了返回地址,以便在子程序执行完毕后能够返回调用点继续执行。
    • 行为: 执行 call 时,当前指令的下一条指令的地址会被压入堆栈(作为返回地址),然后程序跳转到目标地址。子程序执行完后,通过 ret 指令可以从堆栈中弹出返回地址并跳回原来的调用点。
    • 应用场景: call 主要用于函数调用,确保在执行完子程序后程序能够继续从调用点之后的指令执行。

2. 栈操作

  • jmp:

    • jmp 指令不会涉及栈的操作。它只是简单地修改指令指针(IP/EIP/RIP),所以不会保存任何返回地址。
    • 因此,jmp 后执行的代码通常不会返回原位置,除非代码显式使用 jmpcall 来跳回。
  • call:

    • call 指令在跳转前会自动将当前指令的下一条指令的地址压入栈中。这一操作使得在子程序执行完后,程序可以通过 ret 指令从栈中弹出该地址,并跳回到调用点继续执行。
    • 这使得 call 非常适合用于函数调用,因为它支持在执行完子程序后返回原来的调用位置。

3. 结合内核中的 switch_to 例子

  • 在内核的上下文切换中,jmpcall 有不同的应用场景。

    • jmp 的应用: 在 switch_to 宏中,jmp __switch_to 用于直接跳转到上下文切换函数 __switch_tojmp 的作用是切换到另一个任务,并立即开始执行该任务的代码,而不需要保存当前代码的位置,因为上下文切换不需要返回到原来的位置。

    • call 的应用: 如果内核希望在执行完一个子任务后继续执行当前的任务,比如在系统调用或者中断处理程序中,通常会使用 call。它确保任务执行完后能够通过 ret 返回调用点,从而继续执行原来的代码。

  • 内核上下文切换的行为:

    • jmp __switch_to 会导致跳转到 __switch_to 函数,而不需要返回。而 call 会将返回地址(即 1: 标签的地址)保存到栈中,确保在 __switch_to 执行完后能够通过 ret 返回到 1: 处继续执行。
  • #define switch_to(prev,next,last) do {					\unsigned long esi,edi;						\asm volatile("pushfl\n\t"					\"pushl %%ebp\n\t"					\/*** 把esp的内容保存到prev->thread.esp中* 这样该字段指向prev内核栈的栈顶。*/"movl %%esp,%0\n\t"	/* save ESP */		\/*** 将next->thread.esp装入到esp.* 此时,内核开始在next的栈上进行操作。这条指令实际上完成了从prev到next的切换。* 由于进程描述符的地址和内核栈的地址紧挨着,所以改变内核栈意味着改变当前进程。*/"movl %5,%%esp\n\t"	/* restore ESP */	\/*** 将标记为1f的地址存入prev->thread.eip.* 当被替换的进程重新恢复执行时,进程执行被标记为1f的那条指令。*/"movl $1f,%1\n\t"		/* save EIP */		\/*** 将next->thread.eip的值保存到next的内核栈中。* 这样,_switch_to调用ret返回时,就会跳转到next->thread.eip执行。* 这个地址一般情况下就会是1f.*/"pushl %6\n\t"		/* restore EIP */	\/*** 注意,这里不是用call,是jmp,这样,上一条语句中压入的eip地址就可以执行了。*/"jmp __switch_to\n"				\/*** 到这里,进程A再次获得CPU。它从栈中弹出ebp和eflags。*/"1:\t"						\"popl %%ebp\n\t"					\"popfl"						\:"=m" (prev->thread.esp),"=m" (prev->thread.eip),	\/* last被作为输出参数,它的值会由eax赋给它。 */"=a" (last),"=S" (esi),"=D" (edi)			\:"m" (next->thread.esp),"m" (next->thread.eip),	\"2" (prev), "d" (next));				\
    } while (0)

4. 总结

  • jmp:

    • 用于无条件跳转,不保存返回地址。
    • 改变程序执行流,但不会返回到原跳转点。
  • call:

    • 用于调用子程序,保存返回地址。
    • 在子程序执行完毕后,可以通过 ret 返回调用点继续执行。
  • 在操作系统内核中,jmp 常用于上下文切换等不需要返回的场景,而 call 则用于函数调用,确保在执行完毕后返回继续执行。

这篇关于汇编语句中的 jmp 与 call 指令的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1106882

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

工作常用指令与快捷键

Git提交代码 git fetch  git add .  git commit -m “desc”  git pull  git push Git查看当前分支 git symbolic-ref --short -q HEAD Git创建新的分支并切换 git checkout -b XXXXXXXXXXXXXX git push origin XXXXXXXXXXXXXX

笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel

kernel起始与ENTRY(stext),和uboot一样,都是从汇编阶段开始的,因为对于kernel而言,还没进行栈的维护,所以无法使用c语言。_HEAD定义了后面代码属于段名为.head .text的段。         内核起始部分代码被解压代码调用,前面关于uboot的文章中有提到过(eg:zImage)。uboot启动是无条件的,只要代码的位置对,上电就工作,kern

AutoGen Function Call 函数调用解析(一)

目录 一、AutoGen Function Call 1.1 register_for_llm 注册调用 1.2 register_for_execution 注册执行 1.3 三种注册方法 1.3.1 函数定义和注册分开 1.3.2 定义函数时注册 1.3.3  register_function 函数注册 二、实例 本文主要对 AutoGen Function Call

Android中如何实现adb向应用发送特定指令并接收返回

1 ADB发送命令给应用 1.1 发送自定义广播给系统或应用 adb shell am broadcast 是 Android Debug Bridge (ADB) 中用于向 Android 系统发送广播的命令。通过这个命令,开发者可以发送自定义广播给系统或应用,触发应用中的广播接收器(BroadcastReceiver)。广播机制是 Android 的一种组件通信方式,应用可以监听广播来执行

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

【Python知识宝库】上下文管理器与with语句:资源管理的优雅方式

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、什么是上下文管理器?二、上下文管理器的实现三、使用内置上下文管理器四、使用`contextlib`模块五、总结 前言 在Python编程中,资源管理是一个重要的主题,尤其是在处理文件、网络连接和数据库

mysql中导入txt文件数据的操作指令

1 表tt的格式:    CREATE TABLE `tt` (   `ind` int NOT NULL auto_increment,   `name` char(100) default NULL,   PRIMARY KEY  (`ind`)  )   2 文件d.txt的内容示例:  1,a  2,b  3,c

可选择的反思指令微调

论文:https://arxiv.org/pdf/2402.10110代码:GitHub - tianyi-lab/Reflection_Tuning: [ACL'24] Selective Reflection-Tuning: Student-Selected Data Recycling for LLM Instruction-Tuning机构:马里兰大学, Adobe Research领

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键