对在汇编中保存变量的多种方法感到困惑,又名 .skip .equ 和 .quad



亲爱的堆栈溢出用户!

试图在这里学习汇编,我偶然发现了这样一个事实,到目前为止,我已经找到了三种使用汇编(AT&T语法)创建变量的方法:

.equ生成变量

.skip为变量保留特定数量的存储

.quad/long/word/byte创建一个小变量。

到目前为止,我收集的唯一区别是.quad方法可能导致变量在特定条件下执行(并且.skip像堆内存一样工作?我想?

所以至少,我想知道,有什么理由使用任何特定的方法吗?您认为哪一个最适合用于存储字符串、整数以及用户的一些输入等内容?


Edit:按照fuz的解释,我构造了以下代码来测试差异:

.data
bar: .int 128
.equ bob, 128
.bss
buf: .skip 128
buf1: .skip bar
buf2: .skip bob
.text
.global main
main:
mov $256, %rax
mov %rax, bar
mov %rax, bob
mov %rax, buf
ret

预期行为:
buf1: .skip barmov %rax, bob外的所有作品。

实际行为:
buf1: .skip bar外的所有作品。错误test.s:11: Error: .space specifies non-absolute value出现。

问题:
为什么我可以在运行时更改bob

第一个指令.equ用于定义符号常量。 形式的指令

.equ foo, 42

也可以拼写为

foo=    42

并将符号foo设置为值 42。 每当你提到符号foo时,汇编器或链接器将替换值42。 至关重要的是,这不是一个变量。 不能在运行时更改foo的值,并且foo不会存储在程序中的任何位置。 另一方面,作为一个符号常量,你可以在任何可以使用数字的地方使用foo。 例如,您可以跳过foo个字节

.skip foo

如果foo不是符号常数,您将无法做到这一点。

至于其他人,这些从根本上只是保留内存区域的不同方法。.byte保留 1 个字节,.word保留 2 个字节,.long保留 4 个字节,.quad保留 8 个字节。 您需要在指令之后给出内存将获得的初始值:

.int 23

保留 4 个字节的内存并将数字 23 写入该内存。 如果要为该内存区域命名,请在前面加上一个标签:

bar:    .int 23

.skip指令与此类似,但保留您告诉它的字节数。 但是,您不能设置它们的初始值,它们将始终为零。 例如,要保留 100 字节的缓冲区,请执行

buf:    .skip 100

请注意,对于所有这些,将指令放置在哪里都很重要。 内存保留在当前部分中。 因此,如果将这些指令放入执行路径中,数据将作为代码执行。 如果您希望能够写入保留的内存,则需要将指令放入可写部分,例如.data

.data
foo:    .int 42
bar:    .byte 23

对于使用.skip保留的缓冲区,将它们放入.bss部分可能会很有用,因为这会减小磁盘上可执行文件的大小。 您只能在.bss中保留.skip或类似的存储(即初始内存内容均为零)。 否则,它的行为与.data相同。

.bss
buf:    .skip 100

相关内容

最新更新