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
vsasciz
?因此,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
vsasciz
?因此,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寻址模式下的基还是索引。