gpt4 book ai didi

assembly - x86 汇编器中 "data label"的功能是什么?

转载 作者:行者123 更新时间:2023-12-02 08:02:18 26 4
gpt4 key购买 nike

我目前正在按照 Kip Irvine 的“汇编语言 x86 编程”一书学习汇编编程。

在书中,作者试图解释data label的概念。

A data label identifies the location of a variable, providing a convenient way to reference the variable in code. The following, for example, defines a variable named count:

count DWORD 100

The assembler assigns a numeric address to each label.



所以我的理解是什么 data label是:数据标签 count是一个包含数值的变量,其中数值是内存中的一个位置。当我使用 count在我的代码中,我实际上使用的是内存中该位置包含的值,在本例中为 100。

我对数据标签的理解是否正确?如果有点不正确,有人可以指出错误吗?

最佳答案

标签是一种写入内存地址的符号方式,仅此而已。标签本身不占用空间,只是一种方便的方式,可让您稍后在内存中引用该位置。

(嗯,它们也可以变成目标文件中的符号,以允许在链接时计算数字地址,而不是在汇编时。但是对于在同一文件中定义和引用的标签,这种额外的复杂性通常是不可见的;见下文关于地址是链接时间常数,而不是汇编时间。)

例如

; NASM syntax, but the concepts apply exactly to MASM as well
; For MASM, you may need BYTE PTR or whatever size overrides in loads.
section .rodata ; or section .data if you want to be able to store here, too.
COUNT:
db 0x12
FOO:
db 0
BAR:
dw 0x80FF ; same as db 0xff, 0x80

4 字节负载,如 mov eax, [COUNT]将得到 0x80FF0012(因为 x86 是小端)。来自 FOO 的 2 字节加载喜欢 mov cx, [FOO]将得到 0xFF00。

您实际上可能会以这种方式使用来自常量的重叠负载,例如带有字符串,其中一些是其他字符串的子字符串。对于以空字符结尾的字符串,只有常见的后缀才能以这种方式组合到相同的存储空间中。

现在这是否意味着 COUNT是 4 字节变量还是 1 字节变量?不,也没有。汇编语言并没有真正的“变量”。

变量是一个更高级的概念,您可以在汇编语言中使用标签和保留一些静态空间的汇编指令来实现它 .请注意,标签与 db 是分开的。上面例子中的指令。

但是变量不需要有任何静态存储空间:例如您的循环计数器变量可以(并且通常应该)仅存在于寄存器中。

一个变量甚至不需要有一个固定的位置。它可以在未使用的函数的一部分中溢出到堆栈中,但存在于函数的另一部分的寄存器中。在编译器生成的代码中,变量经常无缘无故地在寄存器之间移动,因为编译器甚至不会尝试为同一个变量使用同一个寄存器。

请注意,MASM 确实根据紧随其后的指令将标签与操作数大小隐式关联。所以你可能必须写 mov eax, dword ptr [count]如果 mov eax, [count]给出操作数大小不匹配错误。

有些人认为这是一个功能,但其他人认为这个魔术操作数大小的东西是完全奇怪的。 NASM 语法没有任何这种魔力。您可以知道一条线将如何组装,而无需去寻找定义标签的位置。 add [count], 1是 NASM 中的错误,因为没有任何内容暗示操作数大小。

不要认为在 C 中使用变量的所有内容都必须在汇编语言程序中具有带有标签的静态存储 .但是,如果您确实想将术语“变量”用于静态数据存储 + 像 Kip Irvine 那样的标签,那么请继续。

另请注意,数据标签与代码标签并不特殊或不同。没有什么能阻止您写作 jmp COUNT .将 12 00 FF 80 解码为 x86 指令的(序列)作为练习留给读者,但是(如果它位于具有执行权限的页面中),它将被 CPU 提取和解码。

同样,没有什么能阻止您从代码标签中加载数据作为内存操作数。出于性能原因,混合代码和数据通常不是一个好主意(所有 CPU 都使用分离的 L1D 和 L1I 缓存),但这也有效。在典型的操作系统(如 Linux)中,可执行文件的文本段包含代码和只读数据段,并映射有读取和执行权限。 (但不是写权限,因此除非您修改权限,否则尝试存储会出错。)

JIT 编译器将机器代码写入缓冲区,然后跳转到那里。它可能是一个带有标签的静态缓冲区,但更常见的是它是一个动态分配的缓冲区,其地址是一个变量。

静态地址通常是链接时间常数,但通常不是汇编时间常数。 (除非您正在编写引导加载程序,或其他明确加载到已知地址的内容,否则 org 0x100 可能很有用。)这意味着您可以执行 mov al, [COUNT+2] ,但不是 mov al, [COUNT*2] . (对象文件格式支持整数位移,但不支持其他数学运算符)。

在 PIC 代码中,标签地址甚至不是链接时间常数,但至少在 64 位 PIC 代码中,从代码到数据标签的偏移量是链接时间常数,因此无需额外级别即可使用 RIP 相对寻址间接(通过全局偏移表)。

关于assembly - x86 汇编器中 "data label"的功能是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44742872/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com