x86中汇编代码的说明

时间:2015-03-28 02:56:53

标签: c assembly

#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个字节,char *argv[]占4个,int argc占8个,a,我们为什么会b占40个字节?帐号为12 - &gt; 8 + 4 + 8 + 12 = 32?

我也在努力查看strcpy发生的位置以及两个内存地址$0x80c5b080x8049c60的原因。

2 个答案:

答案 0 :(得分:0)

局部变量后可能会有一些填充     因为gets()的参数需要(32位对齐)空间     以及将通过呼叫指令保存的PC寄存器。

注意:ebp寄存器必须指向下一个可用的堆栈地址     在本地堆栈框架之后。

注意:永远不要使用gets()函数,     有几个原因。请改用fgets()

编译器将strcpy()替换为宏调用。     该宏产生了以下内容:

mov $0x80c5b08,%edx
lea -0xd(%ebp),%eax
mov (%edx),%edx
  

我也在努力查看strcpy()发生的位置以及两个内存地址$ 0x80c5b08和0x8049c60&#34;

的原因

0x80c5b08是要复制到变量中的文字的地址。

0x8049c60是gets()函数的链接地址。

答案 1 :(得分:0)

好吧,我会尽我所能给你,但我的集会有点生疏。首先,让我们从您所看到的内容开始。使用AT&amp; T语法,与英特尔语法(operation data register)相比,您基本上必须向后读取地址操作(operation register data),这是某些人更喜欢阅读英特尔的原因之一。

从概述的角度来看,汇编调用并不难以消化。如果查看前两个命令,第一个命令会将先前的base pointer地址推送到堆栈以保存它。 (当该程序退出时,将恢复先前的基本指针地址,这是调用例程中的执行将重新拾取的位置)。第二行将此程序的base pointer地址移动到current stack pointer地址(堆栈顶部)以开始执行程序。这两行都称为assembly prolog

push %ebp
mov %esp,%ebp

来自subtracts 40 bytes (28 hex)的下一行stack pointer(堆栈增长较低)为局部变量ab创建空间,其中&#34; nop&# 34;数据和gets的结果将被复制。我不确定它尝试实现的精确对齐,但a的存储空间为5个字节且b 10。

sub $0x28,%esp

以下行将指针地址0x80c5b08移动到通用dx寄存器(edx,用于80386 32位寄存器)。在汇编中,在使用它之前,将要操作的数据的地址放入其中一个CPU寄存器中。在这里,它看起来是将内存地址放在&#34; nop&#34;在edx

mov $0x80c5b08,%edx

下一个调用lea 加载有效地址将内存地址(偏移量)base pointer - 14(0xd十六进制)字节复制到eax寄存器中。起始地址为a,以便字符串&#34; nop&#34;可以在那里复制。

lea -0xd(%ebp),%eax

以下对mov的调用将edx指向的数据复制到eax中指定的内存位置。复制&#34; nop&#34;到a

mov (%edx),%edx
mov %edx,(%eax)

下一个leabase pointer - 23(0x17十六进制)b的内存地址加载到eax中,mov将地址放在堆栈之前调用gets填充该位置的内存。

lea -0x17(%ebp),%eax
mov %eax,(%esp)

call 0x8049c60 <gets>

然后,在调用a之前,有指令将bprintf的内存地址以及字符串的静态部分的地址加载到字符串。希望这会有所帮助。