为什么不能在气体中使用标签代替.set
?
.data
.globl _start
str: .asciz "Hello world"
len: .long 13 #if used len = 13, no problem
.text
_start:
mov $1, %eax
mov $1, %edi
movabs $str, %rsi
mov $len, %rdx
syscall
mov $60, %rax
xor %edi, %edi
syscall
这给了我一个错误。我怀疑符号len
会显示地址.data+0xd
吗?并移至R_X86_64_32
?因此,我声明的变量不是从值13
声明的变量,而是从上述地址获取值的变量?那么最后,len
不是常规变量而是指针吗?
输出:
@@ @�� @ld
@ @ @a.ostrlen__bss_start_edata_end.symtab.strtab.shstrtab.note.gnu.property.text.data .@(4 @ !%=!:
这里的问题夫妇:
$
中的mov $len, %rdx
在RDX中放置len
的地址。如果删除它,它将使用您想要的len
(13)中的内容。.quad
而不是.long
,它们分别是64位和32位。如果您确实希望len
成为long
,则应使用movzx len, %rdx
。这会将len
处的32位值零扩展到RDX。如果没有这个,如果您说.byte 0xc
,那么您将获得更大的数量。mov len, %edx
,它与movzx
基本上具有相同的功能,因为将32位移入64位寄存器会清除前32位。但是,我认为这有点使含义模糊不清。str
处的数据长度为12个字符,包括空字节,而不是13个字符。如果改为使用len: .quad . - str
,则可以避免每次都要重新计算。 .
表示当前地址。关于len = 13
(又称.set len, 13
)为什么起作用的原因,mov $len, %rdx
变成了mov $13, %rdx
,它只是将64位13转换为RDX。如果$
不存在,它将移入您不想要的存储器地址13中的内容。如果这样选择,还可以使用#define len $13
,这将在以后消除对$
的需要,但是在这种情况下,我不建议这样做。
最后,我会这样做:
.data
.globl _start
str:
.asciz "Hello world"
len:
.quad . - str
.text
_start:
// Write to STDOUT
mov $1, %eax
mov $1, %edi
movabs $str, %rsi
mov len, %rdx
syscall
// Exit
mov $60, %rax
xor %edi, %edi
syscall