如何获取变量的地址并在 nasm x86 程序集中取消引用它? [英] how to get address of variable and dereference it in nasm x86 assembly?

查看:39
本文介绍了如何获取变量的地址并在 nasm x86 程序集中取消引用它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

in c language we use & to get the address of a variable and * to dereference the variable.


    int variable=10; 
    int *pointer;
    pointer = &variable;


如何在 nasm x86 汇编语言中做到这一点.
我阅读了 nasm 手册,发现 [ variable_address ] 的工作方式类似于取消引用.(我可能错了).


How to do it in nasm x86 assembly language.
i read nasm manual and found that [ variable_address ] works like dereferencing.( i maybe wrong ).

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 中的指针和取消引用.



i executed this code it prints nothing. i can't understand what is wrong with my code. need your help to understand pointer and dereferencing in nasm x86.

推荐答案

程序集中没有变量.(*)

There are no variables in assembly. (*)

variable db 'A'

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

Does several things. It defines assembly-time symbol variable, which is like bookmark into memory, containing address of *here* in the time of compilation. It's same thing as doing label on empty line like:

variable:

db 'A' 指令是定义字节",你给它一个单字节值来定义,所以它会将单字节生成为结果机器码,值为 0x4165 十进制.这就是ASCII编码中大写字母A的值.

The db 'A' directive is "define byte", and you give it single byte value to be defined, so it will produce single byte into resulting machine code with value 0x41 or 65 in decimal. That's the value of big letter A in ASCII encoding.

那么:

mov ecx , [variable]

从地址variable的内存单元加载4个字节,这意味着低8位ecx将包含值65,并且高 24 位将包含一些垃圾,这些垃圾恰好位于 'A' 之后的以下 3 个字节中(您会使用 db 'ABCD',然后 ecx 将等于值 0x44434241('D' 'C' 'B' 'A' 字母,由于很少 -x86 上 dword 值的 endian 编码).

Does load 4 bytes from memory cells at address variable, which means the low 8 bits ecx will contain the value 65, and the upper 24 bits will contain some junk which happened to reside in the following 3 bytes after the 'A' .. (would you use db 'ABCD', then the ecx would be equal to value 0x44434241 ('D' 'C' 'B' 'A' letters, "reversed" in bits due to little-endian encoding of dword values on x86).

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

But the sys_write expect the ecx to hold address of memory, where the content bytes are stored, so you need instead:

mov ecx, variable

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

That will in NASM load address of the data into ecx.

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

(in MASM/TASM this would instead assemble as mov ecx,[variable] and to get address you have to use mov ecx, OFFSET variable, in case you happen to find some MASM/TASM example, be aware of the syntax difference).

*) 有关无变量"的更多信息.请记住,在组装时您处于机器级别.在机器级别有计算机内存,它可以按字节寻址(在 x86 平台上!有一些平台,内存可以按不同大小寻址,它们并不常见,但在微控制器世界中你可能会发现一些).因此,通过使用一些内存地址,您可以访问物理内存芯片中的某些特定字节(内存芯片中的哪个特定物理位置被寻址取决于您的平台,现代操作系统通常会给用户应用程序虚拟寻址空间,转换为CPU 动态地、透明地获取物理地址,无需打扰用户代码进行转换).

*) some more info about "no variables". Keep in mind in assembly you are on the machine level. On the machine level there is computer memory, which is addressable by bytes (on x86 platform! There are some platforms, where memory may be addressable by different size, they are not common, but in micro-controllers world you may find some). So by using some memory address, you can access some particular byte(s) in the physical memory chip (which particular physical place in memory chip is addressed depends on your platform, the modern OS will usually give user application virtual addressing space, translated to physical addresses by CPU on the fly, transparently, without bothering user code about that translation).

变量"、数组"、字符串"等所有高级逻辑概念都只是内存中的一堆字节值,所有这些逻辑含义都由正在执行的指令赋予内存数据.当你在没有指令上下文的情况下查看这些数据时,它们只是内存中的一些字节值,仅此而已.

All the advanced logical concepts like "variables", "arrays", "strings", etc... are just bunch of byte values in memory, and all that logical meaning is given to the memory data by the instructions being executed. When you look at those data without the context of the instructions, they are just some byte values in memory, nothing more.

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

So if you are not precise with your code, and you access single-byte "variable" by instruction fetching dword, like you did in your mov ecx,[variable] example, there's nothing wrong about that from the machine point of view, and it will happily fetch 4 bytes of memory into ecx register, nor the NASM is bothered to report you, that you are probably out-of-bounds accessing memory beyond your original variable definition. This is sort of stupid behaviour, if you think in terms like "variables", and other high-level programming languages concepts. But assembly is not intended for such work, actually having the full control over machine is the main purpose of assembly, and if you want to fetch 4 bytes, you can, it's all up to programmer. It just requires tremendous amount of precision, and attention to detail, staying aware of your memory structures layout, and using correct instructions with desired memory operand sizes, like movzx ecx,byte [variable] to load only single byte from memory, and zero-extend that value into full 32b value in the target ecx register.

这篇关于如何获取变量的地址并在 nasm x86 程序集中取消引用它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆