程序集retn,jmp,进程寄存器

问题描述 投票:-1回答:3

我最近开始使用汇编语言进行C ++编程。我想澄清一些事情。

根据我的阅读,指令指针从retn指令获取它应该执行的地址。它不会像做jmp一样,因为jmp也设置指令指针?

如果我是对的,retnjmp有什么区别?如果我错了,有人可以解释C伪代码吗?

什么是无限循环的装配等价物?

我读到EAX,EBX,ECX,EDX可以互换,但它们有什么区别吗?如果是这样,我应该在哪种情况下专门使用EAX/EBX/ECX/EDX

assembly x86 cpu-registers eip
3个回答
3
投票

你似乎在谈论子程序调用,所以这里是低调。

当你调用子程序时,它看起来像这样(地址会有所不同,但我不想让你混淆可变长度的指令):

1234  call 8888
1235  <next instruction>

会发生的是,call首先将下一个指令指针1235放入堆栈(后进先出数据结构),然后将指令指针设置为您正在调用的任何内容,在这种情况下为8888

之后,回归在8889完成:

8888  mov eax, 0
8889  ret

返回的作用就是从堆栈中弹出第一个值(即1235,它被调用推送)并将其加载到指令指针中。所以这不是告诉你去哪里的回报,而是通过电话推送到堆栈的信息。

如果你在子程序结束时有一个jmp指令,它只能返回到代码中的一个点(折扣你现在可以用其他寻址模式做的所有精彩的事情):

8889  jmp 1235

通过使用返回,您可以返回到您来自的任何地方,无论它在哪里。


无限循环的汇编程序可以简单如下:

loopy:
    jmp loopy

至于寄存器,eaxebxecxedx被认为是通用寄存器。这将它们与更特殊用途的寄存器区分开来,例如堆栈指针,基指针,源和目标索引等,它们根据其用途具有专门的指令。

ax可能在x86架构的早期迭代中有一些额外的功能,但我不确定是否仍然如此。如果你正在编写自己的东西,你应该能够互换使用它们。如果您正在关注API或ABI,则需要遵循它所施加的规则(例如eax保存系统调用号的Linux系统调用接口)。


1
投票

retjmp在C / C ++函数方面的差异与此类似:

int foo()
{
   int x = 3+4;

   if(x < 10)
      goto Quit;    <- similar to jmp

   x += 10;

 Quit:
   return x;     <- similar to ret

}

当你在C中执行return时,在机器级别上实际发生的事情要复杂得多,因为经常会执行额外的代码,例如将返回值放在eax中并清理堆栈。在C ++中,本地对象也会被删除,但是ultiate和函数将是ret指令。

什么是无限循环的装配等价物?

while(1);

就好像

000000 jmp 000000

或者更高级

00000  inc ecx
00001  jmp 00000

通用寄存器。在某些情况下,您可以混合寄存器并根据需要使用它们。对于某些指令,他们希望使用特定的寄存器。您必须查阅说明手册以查看情况。

一个例子是movsw,它要求你使用(E)SI(E)DI,所以在这种情况下你不能自由选择。如果你使用rep movsw,也可以使用额外的(E)CX。通常,汇编程序知道哪些寄存器对于forxtruction有效并且会给出错误消息,但当然,您应该查看手册以确保,因为如果汇编程序不能抛出错误,您可能会得到意外的结果。


0
投票

eaxedx是除法中的隐式操作数,并且是乘法的宽结果版本。还有一些特殊的符号扩展指令,仅对rax(操作码98)的部分操作或将eax符号扩展为edx:eax(操作码99)。十进制数学指令都适用于eax的部分。

ecx(井cl真的但足够接近)是唯一可以在Haswell(它引入sarxshlxshrx,所有这些都可以通过任何GPR转移)之前转移的寄存器。 ecx也被重复前缀用作计数器。 pcmp*stri把长度放在ecx

许多专用指令没有明确的操作数,而是为某些GPR指定特殊含义,例如cpuidrdpmcrdtscwrmsrxgetbvxsave。通常edx:eax,经常ecx,很少ebx。你可能不需要处理这些问题。

© www.soinside.com 2019 - 2024. All rights reserved.