Assembly 理解英特尔汇编中的%rip寄存器
关于以下小代码,在另一篇文章中说明了结构的大小以及正确对齐数据的所有可能性:Assembly 理解英特尔汇编中的%rip寄存器,assembly,x86-64,intel,mov,addressing-mode,Assembly,X86 64,Intel,Mov,Addressing Mode,关于以下小代码,在另一篇文章中说明了结构的大小以及正确对齐数据的所有可能性: struct { char Data1; short Data2; int Data3; char Data4; } x; unsigned fun ( void ) { x.Data1=1; x.Data2=2; x.Data3=3; x.Data4=4; return(sizeof(x)); } 我得到了相应的反汇编(64位) 0000000000000000:
struct
{
char Data1;
short Data2;
int Data3;
char Data4;
} x;
unsigned fun ( void )
{
x.Data1=1;
x.Data2=2;
x.Data3=3;
x.Data4=4;
return(sizeof(x));
}
我得到了相应的反汇编(64位)
0000000000000000:
0:55推送%rbp
1:48 89 e5 mov%rsp,%rbp
4:c6 05 00 01 movb$0x1,0x0(%rip)#b
b:66 c7 05 00 movw$0x2,0x0(%rip)#14
12: 02 00
14:c7 05 00 03移动$0x3,0x0(%rip)#1e
1b:00
1e:c6 05 00 04 movb$0x4,0x0(%rip)#25
25:b8 0c 00 mov$0xc,%eax
2a:5d pop%rbp
2b:c3-retq
我不知道如何计算位于右边的术语,它似乎是所使用的局部变量的地址。此外,我不知道如何用%rip寄存器
您能否举例说明%rip
与%rsp
或%rbp
之间的联系,尤其是在我使用移动
指令计算地址时 RIP寻址总是相对于RIP(64位指令指针)寄存器。因此,它只能用于全局变量。0偏移量等于RIP寻址指令之后的以下指令的地址。例如:
mov al,[rip+2] al=53
jmp short next (length=2 bytes)
db 53
next:
mov bl,[rip-7] (length=6 bytes) bl=53
通常情况下,您不会将数据与代码直接混合在一起,除非是作为即时数据,但这表明了如果您实际使用非常小的偏移量运行代码,会发生什么情况
在代码中,您无法查看和检查偏移量(您可以看到四个零),因为您反汇编了.o
。使用objdump-drwC
在反汇编时显示符号名称/重新定位。当您将此对象链接到可执行文件时,链接器将填充它们
访问与“rbp”相关的局部变量的示例:
push rbp ;save rbp
mov rbp,rsp ;rbp = pointer to return address (8 bytes)
sub rsp,64 ;reserve 64 bytes for local variables
mov rax,[rbp+8]; rax = the last stack-passed qword parameter (if any)
mov rdx,[rbp]; rdx = return address
mov rcx,[rbp-8]; rcx = first qword local variable (this is undefined now)
mov r8, [rbp-16]; r8 = second qword local variable (this is undefined now)
.
.
mov rsp,rbp
pop rbp
ret
没有这种关系,rip
是指令指针(因此得名)。你不能相对于它来称呼当地人。请注意,x
不是本地代码。还要注意,您在中间对象文件上使用了objdump,因此没有获得正确的偏移量。您可能希望在链接的可执行文件上运行它,和/或使用-r
选项查看重定位条目。不,它会按指令的字节数递增。它指向下一个指令。你为什么不在那个问题上问这个?将对象反汇编与链接反汇编进行比较,以查看发生了什么。链接器填写了指令的其余部分,即rip的地址/偏移量。我当时正在显示生成的-m32 vs-m64指令,但这并没有完全说明链接版本的情况。@youpilat13它是RIP
,而不是RPI
。(“指令指针”不是“指针指令”)。同样在32b模式下,使用32b变体eip
,在16b模式下使用16bip
部件rip
没有8位别名(如rax
有al
)。movb$0x4,0x0
将字节值4
存储在绝对地址0
的内存中movb$0x4,0x0(%rip)
将字节值4
存储在绝对地址rip+0
处的内存中,即相对于rip地址0
。这与使用其他寄存器寻址相同,比如movb$4,0(%edi)
。区别在于,rip
在计算时指向下一条指令的开始。因此,使用rip
进行相对寻址允许编译器生成与“PIC”位置无关的代码。然后,操作系统需要将数据+代码加载到一起,以保持它们之间的相对位置;看起来OP反汇编了一个.o
,而不是一个链接的可执行文件。位置无关的代码不需要每次加载时都进行运行时修复;这是RIP相对寻址的最大优势之一。
push rbp ;save rbp
mov rbp,rsp ;rbp = pointer to return address (8 bytes)
sub rsp,64 ;reserve 64 bytes for local variables
mov rax,[rbp+8]; rax = the last stack-passed qword parameter (if any)
mov rdx,[rbp]; rdx = return address
mov rcx,[rbp-8]; rcx = first qword local variable (this is undefined now)
mov r8, [rbp-16]; r8 = second qword local variable (this is undefined now)
.
.
mov rsp,rbp
pop rbp
ret