C 32位和64位处理器中堆栈的区别
我在gdb中为32位和64位intel处理器反汇编了以下代码C 32位和64位处理器中堆栈的区别,c,assembly,gdb,disassembly,C,Assembly,Gdb,Disassembly,我在gdb中为32位和64位intel处理器反汇编了以下代码 void main() { 5 char *args[2]; 6 7 args[0] = "/bin/sh"; 8 args[1] = NULL; 9 execve(args[0],args,NULL); 10 exit(0); 11 } 下面是生成的汇编代码 对于64位 Dump of assembler code for function main: 0x000000
void main() {
5 char *args[2];
6
7 args[0] = "/bin/sh";
8 args[1] = NULL;
9 execve(args[0],args,NULL);
10 exit(0);
11 }
下面是生成的汇编代码
对于64位
Dump of assembler code for function main:
0x000000000040105e <+0>: push %rbp
0x000000000040105f <+1>: mov %rsp,%rbp
0x0000000000401062 <+4>: sub $0x10,%rsp
0x0000000000401066 <+8>: movq $0x493564,-0x10(%rbp) ; <- this line
0x000000000040106e <+16>: movq $0x0,-0x8(%rbp)
0x0000000000401076 <+24>: mov -0x10(%rbp),%rax
0x000000000040107a <+28>: lea -0x10(%rbp),%rcx
0x000000000040107e <+32>: mov $0x0,%edx
0x0000000000401083 <+37>: mov %rcx,%rsi
0x0000000000401086 <+40>: mov %rax,%rdi
0x0000000000401089 <+43>: callq 0x433510 <execve>
0x000000000040108e <+48>: mov $0x0,%edi
0x0000000000401093 <+53>: callq 0x407560 <exit>
主函数的汇编程序代码转储:
0x000000000040105e:推送%rbp
0x000000000040105f:mov%rsp,%rbp
0x0000000000401062:子$0x10,%rsp
0x00000000004010066:movq$0x493564,-0x10(%rbp);
是由两个指针组成的数组。在32位机器上,指针(地址,但不一定)为32位宽,而在64位机器上,指针(和从不使用地址)为64位宽
这意味着,当前堆栈帧中堆栈上的区域必须为2*指针\u宽度
,这使得32位机器的8
,64位机器的16
在下面的代码中,您可以看到
movl $0x80027b8, -0x8(%ebp)
movl $0x0, -0x4(%ebp)
。。。将32位DWORD移动到指针(一个字符串地址和一个NULL
)
另一方面,64位代码需要两个DWORD(8字节)来存储地址
movq $0x0, -0x8(%rbp)
movq $0x493564, -0x10(%rbp)
64位系统从rbp声明16位(我想学习的位、字节或字)偏移量,而32位系统从ebp声明8位偏移量-我相信它是以字节为单位的,而不是以位.字节为单位的。偏移量是不同的,因为在64位模式下,一个地址需要8个字节而不是4个字节。你所说的“指针(而不是地址)是64位宽”是什么意思?在
LP64
模式下,指针和地址总是64位宽,所以你的回答让我困惑。@EmployeedRussian抱歉,我的意思是另一种方式。地址可以是64位宽,但仅当它们是虚拟的时。据我所知,物理地址目前不超过52位。当然,在本例中,我们讨论的是虚拟地址,因此该语句不适用。movl$0x0,-0xC(%ebp)
应该是movl$0x0,-0x4(%ebp)
,因为0xfffffc是十进制-4。这是有意义的,因为在内存中arg应该位于arg++之前(arg[0]位于arg[1]之前)。
movl $0x80027b8, -0x8(%ebp)
movl $0x0, -0x4(%ebp)
movq $0x0, -0x8(%rbp)
movq $0x493564, -0x10(%rbp)