如何获取变量的地址并在 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",你给它定义单字节值,所以它会产生单字节到结果机器代码中,值为0x41
或65
十进制。这就是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 值。
在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",你给它定义单字节值,所以它会产生单字节到结果机器代码中,值为0x41
或65
十进制。这就是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 值。