Assembly 组件retn、jmp、进程寄存器 我最近开始用汇编语言编写C++程序。我想澄清几件事

Assembly 组件retn、jmp、进程寄存器 我最近开始用汇编语言编写C++程序。我想澄清几件事,assembly,x86,cpu-registers,eip,Assembly,X86,Cpu Registers,Eip,从我读到的内容来看,指令指针从retn指令中获取下一步应该执行的地址。这是否与执行jmp相同,因为jmp也设置指令指针 如果我是对的,那么retn和jmp之间有什么区别?如果我错了,有人能用C伪代码解释吗 无限循环的程序集等价物是什么 我读到EAX、EBX、ECX、EDX都是可互换的,但它们有什么区别吗?如果是这样的话,在哪种情况下我应该特别使用EAX/EBX/ECX/EDX您似乎在谈论子程序调用,下面是关于它的详细信息 当您调用一个子例程时,它看起来是这样的(地址会有所不同,但我不想让您混淆可

从我读到的内容来看,指令指针从
retn
指令中获取下一步应该执行的地址。这是否与执行
jmp
相同,因为
jmp
也设置指令指针

如果我是对的,那么
retn
jmp
之间有什么区别?如果我错了,有人能用C伪代码解释吗

无限循环的程序集等价物是什么


我读到
EAX、EBX、ECX、EDX都是可互换的,但它们有什么区别吗?如果是这样的话,在哪种情况下我应该特别使用EAX/EBX/ECX/EDX
您似乎在谈论子程序调用,下面是关于它的详细信息

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

返回只需从堆栈中弹出第一个值(即,
1235
,该值由调用推动),并将其加载到指令指针中。所以它不是告诉你去哪里的返回,而是调用推送到堆栈上的信息

如果在子例程的末尾有一条
jmp
指令,它将只能返回到代码中的一个点(暂时不考虑使用其他寻址模式所能做的一切):

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


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

loopy:
    jmp loopy

对于寄存器,
eax
ebx
ecx
edx
被视为通用寄存器。这使它们不同于更特殊用途的寄存器,如堆栈指针、基指针、源和目标索引等,它们根据用途具有专门的指令


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

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

ecx
(well
cl
非常接近)是Haswell之前唯一可以移位的寄存器(它引入了
sarx
shlx
shrx
,所有这些都可以通过任何GPR进行移位)
ecx
也被rep前缀用作计数器
pcmp*stri
将长度放入
ecx


许多专用指令没有明确的操作数,而是为某些GPR分配特殊含义,例如
cpuid
rdpmc
rdtsc
wrmsr
xgetbv
xsave
。通常
edx:eax
,通常也
ecx
,很少
ebx
。您可能不需要太多地处理这些问题。

就C/C++函数而言,
ret
jmp
的区别与此类似:

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

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

   x += 10;

 Quit:
   return x;     <- similar to ret
就像

000000 jmp 000000
或更高级

00000  inc ecx
00001  jmp 00000
通用寄存器。在某些情况下,您可以混合使用寄存器,并根据需要使用它们。对于某些指令,它们希望使用特定的寄存器。您必须查阅使用手册,了解情况

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

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

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

   x += 10;

 Quit:
   return x;     <- similar to ret
while(1);
000000 jmp 000000
00000  inc ecx
00001  jmp 00000