#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(int argc, char *argv[]){
char a[5];
char b[10];
strcpy(a,"nop");
gets(b);
printf("Hello there %s. Value in a is %s.\n",b,a);
exit(0);
}前几条生产线的装配输出显示:
push %ebp
mov %esp,%ebp
sub $0x28,%esp
mov $0x80c5b08,%edx
lea -0xd(%ebp),%eax
mov (%edx),%edx
mov %edx,(%eax)
lea -0x17(%ebp),%eax
mov %eax,(%esp)
call 0x8049c60 <gets>有几个原因让我很困惑。首先,如果sub $0x28,%esp占8字节,int argc占4,a占8,b占12 -> 8+4+8+12 = 32,为什么要使用占40字节的a?
我还在努力了解strcpy在哪里发生,以及这两个内存地址$0x80c5b08和0x8049c60的原因。
发布于 2015-03-28 07:51:55
好吧,我会尽我所能给你,但我的集会有点生疏。首先,让我们从你正在看的东西开始。使用AT&T语法,您基本上必须向后读取地址操作(operation data register),而不是Intel语法(operation register data),这是一些人更喜欢阅读Intel的原因之一。
从概述的角度来看,程序集调用并不难理解。如果您查看前两个命令,第一个命令将前一个base pointer地址推到堆栈上以保存它。(当该程序退出时,将恢复以前的基本指针地址,这是调用例程中的执行将恢复的位置)。第二行将此程序的base pointer地址移动到current stack pointer地址(堆栈顶部),以开始执行程序。这两行都称为assembly prolog。
push %ebp
mov %esp,%ebp下一行subtracts 40 bytes (28 hex)来自stack pointer (堆栈变得更低),为局部变量a和b创建空间,其中将复制"nop“数据和gets的结果。我不知道它试图实现什么样的精确对齐,但是a的存储将是5个字节,而b是10。
sub $0x28,%esp下面一行将指针地址0x80c5b08移动到通用dx寄存器(用于80386 32位寄存器的edx)。在程序集中,在处理数据之前,要将要操作的数据的地址放入其中一个CPU寄存器中。在这里,它看起来是在edx中放置"nop“的内存地址。
mov $0x80c5b08,%edx下一个调用lea 加载有效地址,将内存地址(在偏移量处) base pointer - 14 (0xd十六进制)字节复制到eax寄存器中。开始地址到a,以便字符串"nop“可以复制到那里。
lea -0xd(%ebp),%eax以下对mov的调用将edx指向的数据复制到eax中指定的内存位置。将"nop“复制到a。
mov (%edx),%edx
mov %edx,(%eax)下一个lea将base pointer - 23 (0x17十六进制) b的内存地址加载到eax中,并且mov在调用gets之前将地址放置在堆栈中。
lea -0x17(%ebp),%eax
mov %eax,(%esp)
call 0x8049c60 <gets>之后,会有一些指令来加载a和b的内存地址,以及调用printf之前字符串的静态部分的地址。希望这能帮上忙。
发布于 2015-03-28 03:18:00
在局部变量之后可能有一些填充,因为需要(32位对齐)空间为gets()和PC寄存器的参数,这将通过调用指令保存。
注意:ebp寄存器必须指向本地堆栈帧之后的下一个可用堆栈地址。
注意:不应该使用gets()函数,原因有几点。使用fgets()代替。
用宏调用将strcpy()替换为编译器。该宏产生了以下内容:
mov $0x80c5b08,%edx
lea -0xd(%ebp),%eax
mov (%edx),%edx我还在努力了解
strcpy()在哪里发生,以及这两个内存地址$0x80c5b08和0x8049c60的帐户是什么“
0x80c5b08是要复制到变量中的文字地址。
0x8049c60是gets()函数的链接地址。
https://stackoverflow.com/questions/29313150
复制相似问题