关于AT&T汇编语法中两种间接JMP指令写法差异的技术咨询
AT&T汇编中两段间接跳转代码的区别解析
这个问题的核心在于AT&T汇编语法里符号地址的取值方式和间接跳转的语义,我来给你拆解清楚:
第一段代码:mov $main, %eax; jmp *%eax
咱们一步步看执行逻辑:
mov $main, %eax:这里的$表示取立即数,也就是把标签main对应的内存地址值(比如0x080483e0)直接加载到%eax寄存器里。简单说,就是让%eax存着main代码段的入口地址。jmp *%eax:*是间接跳转的标记,意思是“跳转到寄存器里存储的地址指向的位置”。这里就是跳转到%eax里存的main地址,最终效果和直接写jmp main(直接跳转)完全一样,只是多了一步寄存器中转的操作。
第二段代码:jmp *main
这段的逻辑就完全不同了:jmp *main里的*同样标记间接跳转,但这里的操作数是符号main,AT&T汇编会把它解析为“去main对应的内存地址里读取内容,把这个内容当作跳转的目标地址”。
举个例子更直观:
- 如果
main是代码段的标签,那它对应的地址里存储的是指令的机器码(比如第一条指令是push %ebp,机器码是0x55)。这时候执行jmp *main,会把这个机器码(比如32位下是0x55xxxxxx)当成地址去跳转,这显然是错误的,大概率会触发程序崩溃。 - 只有当
main是一个函数指针变量(比如在.data段定义的.long main,也就是专门存main地址的变量)时,jmp *main才是正确的——它会读取这个变量里存的main地址,然后跳过去。
一句话总结
mov $main, %eax; jmp *%eax:是把main的地址给寄存器,再通过寄存器跳转到main本身,等价于直接跳转main;jmp *main:是把main地址里存的数据当作目标地址跳转,只有当main是指针变量时才合理。
内容的提问来源于stack exchange,提问作者Sairaj




