代码之家  ›  专栏  ›  技术社区  ›  Cam

程序集-.data、.code和寄存器…?

  •  27
  • Cam  · 技术社区  · 15 年前

    所以今天早上我发表了一个关于组装的困惑的问题,我得到了一些真正的帮助,我非常感谢。

    现在我开始着手组装,并开始了解它是如何工作的。

    我觉得我可以理解的事情包括堆栈、中断、二进制/十六进制,以及通常大多数基本操作(jmp、push、mov等)所做的事情。

    我正在努力理解并希望得到帮助的概念如下-如果您能够解决以下任何一个问题,这将是一个巨大的帮助:

    1. .data部分到底发生了什么?这些变量是我们要声明的吗?
    2. 如果是这样,我们可以稍后在代码部分声明变量吗?如果没有,为什么不呢?如果是这样,那么我们如何以及为什么要使用数据部分呢?
    3. 什么是登记簿?它如何与变量进行比较?我的意思是我知道这是一个存储一小部分信息的地方…但对我来说,这听起来就像一个变量。
    4. 如何创建数组?我知道这似乎是随机的,但我很好奇我会怎么做这样的事情。
    5. 对于每个寄存器应该用于什么,是否有一个常见的实践列表?我仍然不能完全理解它们,但我注意到一些人说,例如,应该使用某个寄存器来存储过程中的“返回值”——是否有一个全面的或至少是信息丰富的此类实践列表?
    6. 我学习汇编的原因之一是为了更好地理解我的高级代码背后发生了什么。考虑到这一点——当我在C++中编程时,我经常在思考堆栈和堆。在汇编中,我知道堆栈是什么——堆栈在哪里?

    一些信息:我正在使用masm32和winasm作为一个IDE,我正在使用windows 7。我有很多以前的高级语言编程经验,如C++/Java。


    编辑:谢谢大家的帮助,像往常一样信息量很大!很棒的东西!不过,最后一件事是——我想知道堆栈指针和基指针(esp和ebp)之间的区别是什么。有人能帮我吗?

    编辑:我想我现在明白了……esp总是指向堆栈的顶部。但是,您可以将EBP指向任何您想要的地方。esp是自动处理的,但是你可以用ebp做你想做的任何事情。例如:

    push 6
    push 5
    push 4
    mov EBP, ESP
    push 3
    push 2
    

    在这个场景中,ebp现在指向保存4的地址,而esp现在指向保存2的地址。

    在实际应用程序中,6、5和4可以是函数参数,而3和2可以是该函数中的局部变量。

    2 回复  |  直到 10 年前
        1
  •  32
  •   Carl Norum    10 年前

    让我们按顺序回答!

    1. 数据部分包含任何您希望在系统调用程序入口点之前由系统自动初始化的内容。你是对的,通常全局变量都会在这里结束。零初始化的数据通常不包含在可执行文件中,因为没有理由-生成该空间只需要对程序加载器执行两个指令。一旦程序开始运行,zi和数据区域通常是可互换的。 Wikipedia 有更多的信息。

    2. 当汇编编程时,变量并不真正存在,至少在编写C代码时,它们不存在。你所拥有的只是关于如何布置你的记忆的决定。变量可以在堆栈上,内存中的某个地方,或者只存在于寄存器中。

    3. 寄存器是处理器的内部数据存储器。通常,您只能对处理器寄存器中的值进行操作。您可以将它们的内容加载和存储到内存中,这是计算机工作方式的基本操作。下面是一个简单的例子。这个C代码:

      int a = 5;
      int b = 6;
      int *d = (int *)0x12345678; // assume 0x12345678 is a valid memory pointer
      *d = a + b;
      

      可能会被翻译成一些(简化的)组件,按照以下方式进行:

      load  r1, 5
      load  r2, 6
      load  r4, 0x1234568
      add   r3, r1, r2
      store r4, r3
      

      在这种情况下,您可以将寄存器视为变量,但一般来说,任何一个变量都不必始终保持在同一个寄存器中;根据您的例程有多复杂,它甚至不可能存在。您需要将一些数据推送到堆栈上,弹出其他数据,等等。“变量”是指逻辑数据块,而不是它在内存或寄存器等中的位置。

    4. 数组只是一个连续的内存块-对于本地数组,您可以适当地减少堆栈指针。对于全局数组,可以在数据段中声明该块。

    5. 关于寄存器有很多约定——检查平台的ABI或调用约定文档以了解如何正确使用它们的详细信息。汇编程序文档也可能包含信息。检查 ABI article on wikipedia .

    6. 您的汇编程序可以使同一个系统调用任何C程序都可以,所以您只需调用 malloc() 从堆中获取内存。

        2
  •  16
  •   user257111    15 年前

    我想补充一下。计算机上的程序通常分为三个部分,尽管还有其他部分。

    代码段-.code,.text: http://en.wikipedia.org/wiki/Code_segment

    在计算技术中,代码段 称为文本段或简称为 文本,是用来指 内存或对象文件的一部分 包含可执行指令的。 它有一个固定的大小,通常 只读的。如果文本部分不是 只读,然后是特定的 体系结构允许自我修改 代码。只读代码是可重入的,如果 它可以由多个执行 同时处理。作为记忆 区域,代码段驻留在 内存的较低部分 为了防止堆和 堆栈覆盖时溢出。

    数据段-。数据: http://en.wikipedia.org/wiki/Data_segment

    数据段是其中一个部分 对象文件中的程序或 内存,其中包含全局 变量和静态变量 由程序员初始化。它 有一个固定的大小,因为所有 本节中的数据由 程序之前的程序员 加载。但是,它不是只读的, 因为变量的值可以 在运行时更改。这是在 与罗达塔对比(常数, 只读数据)部分,以及 代码段(也称为文本 段)。

    BSS: http://en.wikipedia.org/wiki/.bss

    在计算机程序设计中,.bss或bss (最初代表Block 由符号开始)被许多人使用 编译器和链接器作为 数据段的一部分,包含 静态变量和全局变量 只装满了 初始零值数据(即 执行开始时)。它经常是 称为“BSS部分”或 “BSS段”。程序加载器 初始化分配给的内存 当它加载 程序。

    寄存器是CPU存储数据或内存地址的设施,如其他人所述。操作是在寄存器上执行的,例如 add eax, ebx 根据汇编语言,这意味着不同的东西。在这种情况下,这转换为将ebx的内容添加到eax,并将其存储在eax(nasm语法)中。GNU AS(AT&T)中的等效值为: movl $ebx, $eax . 集合的不同方言有不同的规则和运算符。因为这个原因,我不是MASM的粉丝——它和NASM、YASM和GNU AS都有很大的不同。

    实际上没有与C.abi进行一般性的交互。abi指定了这是如何发生的;例如,在x86(Unix)上,您将发现一个方法的参数被推到堆栈上,而在Unix上的x86-64中,前几个参数将定位在寄存器中。两个ABI都希望函数的结果存储在EAX/RAX寄存器中。

    下面是一个32位的添加例程,它为Windows和Linux进行组装。

    _Add
        push    ebp             ; create stack frame
        mov     ebp, esp
        mov     eax, [ebp+8]    ; grab the first argument
        mov     ecx, [ebp+12]   ; grab the second argument
        add     eax, ecx        ; sum the arguments
        pop     ebp             ; restore the base pointer
        ret
    

    在这里,你可以明白我的意思。“返回”值在EAX中找到。相比之下,X64版本如下:

    _Add
        push    rbp             ; create stack frame
        mov     rbp, rsp
        mov     eax, edi        ; grab the first argument
        mov     ecx, esi        ; grab the second argument
        add     eax, ecx        ; sum the arguments
        pop     rbp             ; restore the base pointer
        ret
    

    有些文档定义了这类事情。以下是Unix X64 ABI: http://www.x86-64.org/documentation/abi-0.99.pdf . 我相信你可能会找到任何处理器,平台等你需要的ABI。

    如何操作装配中的数组?指针算术。给定的基地址位于 eax 下一个存储的整数将位于 [eax+4] 如果整数的大小为4字节。您可以使用malloc/calloc调用来创建这个空间,也可以调用内存分配系统调用,无论系统上是什么。

    什么是“堆”?根据维基百科的说法,它是为动态内存分配而保留的内存区域。在调用calloc、malloc或内存分配系统调用之前,您不会在程序集中看到它,但它确实存在。

    对这篇文章感到抱歉。

    推荐文章
    1ftw1  ·  Nasm正在构建字符串
    12 年前