如何获取变量的地址并在 nasm x86 程序集中取消引用它?

how to get address of variable and dereference it in nasm x86 assembly?

在c语言中我们使用&来获取变量的地址,*来解引用变量。


    整型变量=10;
    整型*指针;
    指针 = &variable;</pre>
如何在 nasm x86 汇编语言中做到这一点。
我阅读了 nasm 手册,发现 [variable_address] 就像取消引用一样工作。(我可能错了)。

section .data
variable db 'A'
section .text
global _start
_start:
mov eax , 4
mov ebx , 1
mov ecx , [variable]  
mov edx , 8
int 0x80
mov eax ,1
int 0x80



我执行了这段代码,它什么也没打印。我不明白我的代码有什么问题。 需要您的帮助来理解 nasm x86.

中的指针和取消引用

汇编中没有变量。 (*)

variable db 'A'

做几件事。它定义了汇编时符号variable,就像书签一样放入内存中,在编译时包含*这里*的地址。这与在空行上做标签是一样的:

variable:

db 'A'指令是"define byte",你给它定义单字节值,所以它会产生单字节到结果机器代码中,值为0x4165 十进制。这就是ASCII编码中大字母A的值。

然后:

mov ecx , [variable]

从地址 variable 的内存单元加载 4 个字节,这意味着低 8 位 ecx 将包含值 65,而高 24 位将包含一些垃圾它恰好驻留在 'A' 之后的以下 3 个字节中..(你会使用 db 'ABCD',那么 ecx 将等于值 0x44434241'D' 'C' 'B' 'A' 字母,"reversed" 由于 x86 上 dword 值的小端编码)。

但是 sys_write 期望 ecx 保存内存地址,其中存储内容字节,因此您需要:

mov ecx, variable

这将在NASM中将数据的地址加载到ecx

(在 MASM/TASM 中,这会将 assemble 改为 mov ecx,[variable] 并且要获取地址,您必须使用 mov ecx, OFFSET variable,以防您碰巧找到一些 MASM/TASM 示例,请注意语法差异)。


*) 关于 "no variables" 的更多信息。请记住,在组装过程中,您处于机器级别。在机器级别有计算机内存,可以按字节寻址(在 x86 平台上!有一些平台,内存可以按不同的大小寻址,它们并不常见,但在微控制器世界中你可能会找到一些)。因此,通过使用一些内存地址,您可以访问物理内存芯片中的某些特定字节(内存芯片中的哪个特定物理位置被寻址取决于您的平台,现代 OS 通常会给用户应用程序虚拟寻址space,由 CPU 即时、透明地翻译成物理地址,而无需为该翻译打扰用户代码)。

所有高级逻辑概念,如"variables"、"arrays"、"strings"等...都只是内存中的一堆字节值,所有逻辑含义都赋予给正在执行的指令的内存数据。当你在没有指令上下文的情况下查看那些数据时,它们只是内存中的一些字节值,仅此而已。

因此,如果您的代码不准确,并且您通过指令获取 dword 访问单字节 "variable",就像您在 mov ecx,[variable] 示例中所做的那样,没有任何问题从机器的角度来看,它会很乐意将 4 个字节的内存提取到 ecx 寄存器中,NASM 也懒得报告你,你可能正在越界访问内存超出您最初的 variable 定义。这是一种愚蠢的行为,如果你用 "variables" 和其他高级编程语言概念来思考的话。但是汇编并不是为这样的工作而设计的,实际上完全控制机器是汇编的主要目的,如果你想获取 4 个字节,你可以,这完全取决于程序员。它只需要极高的精度和对细节的关注,了解您的内存结构布局,并使用具有所需内存操作数大小的正确指令,例如 movzx ecx,byte [variable] 从内存中仅加载单个字节,并对其进行零扩展将目标 ecx 寄存器中的值转换为完整的 32b 值。