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
(wellcl
非常接近)是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