Assembly 获取程序集中字符串长度的简短形式

Assembly 获取程序集中字符串长度的简短形式,assembly,x86,gnu-assembler,Assembly,X86,Gnu Assembler,要获取字符串的长度,我使用以下函数: string: .asciz "hello world!\n" get_string_length: mov $0, %eax # size goes in rax .L1_loop: movzbw string(,%eax,1), %ebx cmp $0, %ebx je .L1_exit inc %eax jmp .L1_loop .L1_exit: ret

要获取字符串的长度,我使用以下函数:

string:     .asciz "hello world!\n"
get_string_length:
    mov $0, %eax    # size goes in rax
  .L1_loop:
    movzbw string(,%eax,1), %ebx
    cmp $0, %ebx
    je .L1_exit
    inc %eax
    jmp .L1_loop
  .L1_exit:
    ret
然而,我也看到了以下情况:

hello_world:
    .ascii "hello world\n"
    hello_world_len = . - hello_world

以下是如何工作的?这就是
符号,所有这些都是为了得到长度?例如,在此github代码段中:

第一个版本在运行时确定长度,第二个版本在汇编时设置长度

第二个表达式中的
表示当前地址(在数据段中)。然后,表达式

hello_world_len = . - hello_world

从当前地址(由
指示)减去标签
hello\u world:
指示的字符串
.ascii“hello world\n”
的起始地址产生长度值
hello\u world\u len

,第一个版本在运行时确定长度,第二个版本在组装时设置长度

第二个表达式中的
表示当前地址(在数据段中)。然后,表达式

hello_world_len = . - hello_world

从当前地址(由
指示)减去标签
hello\u world:
指示的字符串
.ascii“hello world\n”
的起始地址,得到长度值
hello\u world\u len
,非常感谢,这正是我想要了解的。当与当前地址组合时,
是否被替换?因此,例如,
=10,和
hello\u world
=5。因此hello_world_len=10-5-->用elf文件中的数值
5
替换单词“hello_world_len”?几乎可以。但我更喜欢“set”一词而不是“substitute”,因为它更像是对表达式的评估,而不是文本上的“substitution”。但这只是一个形式上的区别,你的想法是适用的。最后一件事,如果有空终止符,这会为空终止符添加
+1
,比如使用
.ascii
vs
asciz
?因此,
hello
的长度为
5
,而
hello\0
的长度为
6
?在第二个版本中,
.asciz
中的空终止符也被计算在内。所以对于
你好
.ascii
(5)或
.asciz
(6)并不重要。结果将是准确的。在运行时版本中,您必须注意这一点。@samuelbrody1249相关:非常感谢,这正是我想要了解的。当与当前地址组合时,
是否被替换?因此,例如,
=10,和
hello\u world
=5。因此hello_world_len=10-5-->用elf文件中的数值
5
替换单词“hello_world_len”?几乎可以。但我更喜欢“set”一词而不是“substitute”,因为它更像是对表达式的评估,而不是文本上的“substitution”。但这只是一个形式上的区别,你的想法是适用的。最后一件事,如果有空终止符,这会为空终止符添加
+1
,比如使用
.ascii
vs
asciz
?因此,
hello
的长度为
5
,而
hello\0
的长度为
6
?在第二个版本中,
.asciz
中的空终止符也被计算在内。所以对于
你好
.ascii
(5)或
.asciz
(6)并不重要。结果将是准确的。在运行时版本中,您必须注意这一点。@samuelbrody1249相关:请注意,
movzbw字符串(,%eax,1),%ebx
在目标寄存器为dword(
l
size)的情况下,操作数大小不匹配,但指令后缀(
w
)。令人惊讶的是,GAS不会发出警告或出错,只是将其组装为
movzbl
。此外,强制EAX作为索引而不是基,这是毫无意义的低效(代码大小)。此外,EBX通常是保留调用的;ECX或EDX将是另一个临时寄存器的正常选择。@PeterCordes感谢您的反馈,所以应该是
movzbl
,对吗?你的意思是做
string(,%eax,1)
vs.
string(%eax)
?是的,
movzbl string(%eax),%ecx
。您只是在x86寻址模式下添加一个字节偏移量,无论它是基还是索引。请注意,
movzbw string(,%eax,1),%ebx
在作为dword(
l
size)的目标寄存器和指令后缀(
w
)之间存在操作数大小不匹配。令人惊讶的是,GAS不会发出警告或出错,只是将其组装为
movzbl
。此外,强制EAX作为索引而不是基,这是毫无意义的低效(代码大小)。此外,EBX通常是保留调用的;ECX或EDX将是另一个临时寄存器的正常选择。@PeterCordes感谢您的反馈,所以应该是
movzbl
,对吗?你的意思是做
string(,%eax,1)
vs.
string(%eax)
?是的,
movzbl string(%eax),%ecx
。您只需添加一个字节偏移量,无论它是x86寻址模式下的基还是索引。