我有一个简单的C代码:
#include <stdlib.h>
static int x = 4;
static int *p;
int *s;
struct B
{
int *s;
int j;
};
void foo()
{
static int *pointer;
static struct B *c;
c = malloc(sizeof(struct B));
x = 5;
p = &x;
p = s;
pointer = p;
static struct B b;
b.s = &x;
b.j = 9;
}
int main(int argc, char *argv[])
{
static char buf[10] = "";
static char b;
x = 5;
/* OK */
buf[9] = 'A';
b = 'C';
return 0;
}
我得到了objdump
,下面是foo function
:
00000000004004e6 <foo>:
4004e6: 55 push rbp
4004e7: 48 89 e5 mov rbp,rsp
4004ea: bf 10 00 00 00 mov edi,0x10
4004ef: e8 fc fe ff ff call 4003f0 <malloc@plt>
4004f4: 48 89 05 4d 0b 20 00 mov QWORD PTR [rip+0x200b4d],rax # 601048 <c.2532>
4004fb: c7 05 1f 0b 20 00 05 mov DWORD PTR [rip+0x200b1f],0x5 # 601024 <x>
400502: 00 00 00
400505: 48 c7 05 30 0b 20 00 mov QWORD PTR [rip+0x200b30],0x601024 # 601040 <p>
40050c: 24 10 60 00
400510: 48 8b 05 69 0b 20 00 mov rax,QWORD PTR [rip+0x200b69] # 601080 <s>
400517: 48 89 05 22 0b 20 00 mov QWORD PTR [rip+0x200b22],rax # 601040 <p>
40051e: 48 8b 05 1b 0b 20 00 mov rax,QWORD PTR [rip+0x200b1b] # 601040 <p>
400525: 48 89 05 24 0b 20 00 mov QWORD PTR [rip+0x200b24],rax # 601050 <pointer.253
1>
40052c: 48 c7 05 29 0b 20 00 mov QWORD PTR [rip+0x200b29],0x601024 # 601060 <b.2533
>
400533: 24 10 60 00
400537: c7 05 27 0b 20 00 09 mov DWORD PTR [rip+0x200b27],0x9 # 601068 <b.2533+0x8>
40053e: 00 00 00
400541: 90 nop
400542: 5d pop rbp
400543: c3 ret
现在,我可以将此汇编代码与C代码相关联(即,我在理解逻辑上没有任何困难)。我也知道静态/全局变量存储在数据部分而不是堆栈中(如果我在这里错了,请更正我)。但是,我不明白为什么地址算法(与rpi有关的偏移量)每次都不相同。例如考虑以下两个说明:
mov QWORD PTR [rip+0x200b22],rax # 601040 <p>
mov rax,QWORD PTR [rip+0x200b1b] # 601040 <p>
这两个都对应于与指针p
相关的操作。现在,我的问题是为什么两种情况下的地址都不同:
即rip+0x200b22
和rip+0x200b1b
,它们都正在访问指针p
(我相信p
的静态位置是601040)?
答案 0 :(得分:1)
RIP是指令指针。 (R = 64位寄存器名称)。
这两个指令位于不同的地址,因此它们与BSS变量的距离不同。 x86-64倾向于使用RIP相对寻址进行静态存储。 objdump
向您展示了RIP相对寻址模式,并将其解码为# 601040 <p>
的最终绝对地址
({p
和s
应该在BSS中,因为它们没有非零的静态初始值设定项。但是,是的,静态存储。)
相关: