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模式下使用16b
ip
部件
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