首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >x86中装配代码的解释

问x86中装配代码的解释
EN

Stack Overflow用户
提问于 2015-03-28 02:56:53
回答 2查看 1K关注 0票数 2
代码语言:javascript
复制
#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);
}

前几条生产线的装配输出显示:

代码语言:javascript
复制
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的原因。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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。

代码语言:javascript
复制
push %ebp
mov %esp,%ebp

下一行subtracts 40 bytes (28 hex)来自stack pointer (堆栈变得更低),为局部变量a和b创建空间,其中将复制"nop“数据和gets的结果。我不知道它试图实现什么样的精确对齐,但是a的存储将是5个字节,而b是10。

代码语言:javascript
复制
sub $0x28,%esp

下面一行将指针地址0x80c5b08移动到通用dx寄存器(用于80386 32位寄存器的edx)。在程序集中,在处理数据之前,要将要操作的数据的地址放入其中一个CPU寄存器中。在这里,它看起来是在edx中放置"nop“的内存地址。

代码语言:javascript
复制
mov $0x80c5b08,%edx

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

代码语言:javascript
复制
lea -0xd(%ebp),%eax

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

代码语言:javascript
复制
mov (%edx),%edx
mov %edx,(%eax)

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

代码语言:javascript
复制
lea -0x17(%ebp),%eax
mov %eax,(%esp)

call 0x8049c60 <gets>

之后,会有一些指令来加载a和b的内存地址,以及调用printf之前字符串的静态部分的地址。希望这能帮上忙。

票数 0
EN

Stack Overflow用户

发布于 2015-03-28 03:18:00

在局部变量之后可能有一些填充,因为需要(32位对齐)空间为gets()和PC寄存器的参数,这将通过调用指令保存。

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

注意:不应该使用gets()函数,原因有几点。使用fgets()代替。

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

代码语言:javascript
复制
mov $0x80c5b08,%edx
lea -0xd(%ebp),%eax
mov (%edx),%edx

我还在努力了解strcpy()在哪里发生,以及这两个内存地址$0x80c5b08和0x8049c60的帐户是什么“

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29313150

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档