我是一个新手,我正在看一个Hello World程序:
section .data
hello: db 'Hello, World!',10 ; 'Hello, World!' plus a linefeed character
helloLen: equ $-hello ; Length of the 'Hello world!' string
section .text
global _start
_start:
mov eax,4 ; The system call for write (sys_write)
mov ebx,1 ; File descriptor 1 - standard output
mov ecx,hello ; Put the offset of hello in ecx
mov edx,helloLen ; helloLen is a constant, so we don't need to say
; mov edx,[helloLen] to get it's actual value
int 80h ; Call the kernel
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return "code" of 0 (no error)
int 80h;
关于db 'Hello, World!',10
的问题这就是“Hello,World!“字符串以换行符结束,但据我所知,字符串必须以空字符结束,我从另一个来源了解到的是将字符串创建为db "Hello, World!,0
。
如何在字符串的末尾(或内部)添加换行符/换行符,并在最后添加null终止符?
(我确实理解,在给定的程序中,代码是使用给定的长度打印的,这是一个选项,但是null终止的字符串似乎更好,必须为你将要编写的每个字符串提供长度似乎不是很好)
1条答案
按热度按时间ffdz8vbo1#
(我不小心忽略了你的最后一句话,所以这个答案的第一部分是解释你可能已经知道的。我会把它留在这里,以防对未来的读者有帮助。
从我所知道的字符串必须以空字符终止
的确,空结束符是一种非常常见的标记字符串结尾的方式,而且许多函数都设计用于处理这种形式的字符串;例如标准C库中的所有
str*
函数。人们经常使用“字符串”这个词来表示“以空值终止的字符串”,而没有进一步澄清。但是
write
系统调用不是这些函数之一。它不依赖于空终止符来标记要写入的数据的结束;相反,它使用长度参数(您已将其放入edx
寄存器中)来了解应从内存中向文件描述符写入多少字节。如果你仔细想想,它必须是这样的:如果write
使用空终止字符串,那么就不可能使用它来编写需要包含空字节的二进制文件。因此,在程序中,由于您对
hello
消息所做的唯一事情就是将其传递给write
系统调用,因此无需包含终止空字节。它只会浪费一个字节的内存。如果你想包含一个终止空字节(也许是因为你想在
str*
函数,printf
等中使用这个字符串),那么只需附加一个0:你没有提到你使用的汇编器,但它看起来像nasm。nasm文档非常完整,它解释了
db
指令可以接受任意的字符串和数值表达式列表。请注意,如果您保留下面的
helloLen
定义,则该长度将 * 包括 * 终止null,这可能不是您想要的。但是如果你使用的是通过null终止符检测长度的函数,那么你可能根本不需要helloLen
。