寄存器和堆栈的大小在汇编 x86 中的真正含义是什么

Mr.*_*ark 0 x86 assembly

我是汇编新手,我真的很困惑,我读了几篇文章和书籍,但我不明白这是什么意思

在汇编 x86 中,我们有不同的寄存器,每个寄存器都有特定的大小,例如

EAX:32位

Q1-32 位的真正含义是什么?这是否意味着,我只能存储 32 位大小的值?

如果是

Q2 - 如果我有很长的字符串,我如何将该字符串移动到我的寄存器?

Q3 - 我想确切地知道何时应该从堆栈中压入和弹出?

Q4 我可以将我的值存储在寄存器中而无需堆栈,为什么我们有堆栈?解决哪个问题?

如果我们举个例子,这里是我的 C 代码:

#include<stdio.h>

main() 
{
    printf("Hello World");

}
Run Code Online (Sandbox Code Playgroud)

在这里,我们将 Hello world 传递给 printf 函数,无论大小,我都可以传递任何东西,如果我将此代码翻译为汇编,首先我必须将系统调用参数移动到寄存器,然后调用系统调用,然后调用 int 0x80。如果在“你好世界”状态下我有一个段落怎么样?

Q5 - 当我将任何数据移动到寄存器时,我如何选择应该将数据移动到哪个寄存器?

谢谢 。

Joh*_*ger 5

寄存器存储数字。就是这样。这就是他们所做的一切。作为程序员,您如何使用解释这些数字才能使程序正常运行。

  • 每个寄存器的大小为 8、16、32 或 64 位。它们可以存储有符号无符号的数字 - 也就是说,它们的最高位是否被解释为符号位,或者只是作为数字的一部分。请注意,这些数字可能是内存中变量的地址 - 那么有符号性就不是一个因素了。

  • 您可以对数字进行加法、减法或执行许多其他操作。
    将一个放入一个寄存器,将另一个放入另一个寄存器,使用ADDorSUB指令,您将得到结果:

            MOV  EAX, 0x12345678
            MOV  EBX, 0x12345677
            SUB  EAX, EBX        ; EAX now holds the value 1
    
    Run Code Online (Sandbox Code Playgroud)
  • 您可以指向内存中的值。将变量的地址存储在寄存器中,您可以读取和写入这些值:

            .DATA
    xValue  DD   42       ; Save xValue here
    
            .CODE
            MOV  EAX, [xValue]         ; Get the current xValue into EAX
            INC  EAX                   ; Add one to it
            MOV  [xValue], EAX         ; Save it back
    
            INC  [xValue]              ; One line to do the above three
    
            MOV  EBX, OFFSET xValue    ; Point to xValue with EBX
            MOV  EAX, [EBX]            ; Get the current value
            INC  EAX                   ; Add one to it
            MOV  [EBX], EAX            ; Save it back
    
            INC DWORD PTR [EBX]        ; One line to do the above three
    
    Run Code Online (Sandbox Code Playgroud)
  • 你如何传递字符串?
    你不知道。你传递字符串的内存地址,接收函数就知道寄存器中的值就是字符串在内存中的地址。

  • 你为什么要从堆栈中PUSH取出?POP

    • 寄存器的数量有限,因此要执行具有许多不同值的进程,您需要将一些值存储在内存中,将值交换到寄存器中或从寄存器中交换出来以对其进行处理。
    • 您可以为每个变量使用保留的内存区域;或者您可以将值临时保存到堆栈中,而不是为它们保留内存中的特定位置。
    • 请注意,如果您有递归函数,则保留内存区域将不起作用 - 每次通过递归时,您都需要新的内存用于下一次迭代。堆栈非常适合此目的。
    • 有些函数希望它们的参数存储在堆栈上,而不是全局变量中。
  • 您如何知道要使用哪个寄存器?
    这取决于:

    • 如果您正在编写代码,则可以使用您喜欢的任何寄存器 - 除了SP// ,它是为指向堆栈而保留的! ESPRSP
      • 有一些架构约定:
        • 如果你要使用REPor指令,那么LOOP你需要使用CX//来保存计数;ECXRCX
        • 如果您要使用、、LODS和指令,那么您需要使用/// 、//和/或// STOSCMPSMOVSALAXEAXRAXSIESIRSIDIEDIRDI
      • 有一些历史约定,但在 32 位和 64 位编程中不再需要这些约定:
        • BXSIDIBP是唯一可以索引内存的寄存器,因此这就是它们的用途;
    • 如果您没有编写要调用的代码,那么它应该指定(或使用通用标准)哪些寄存器保存哪些参数,以及它使用哪个寄存器作为返回值。