Tho*_*hor 1 string null x86 assembly masm
我目前正在按照 Kip Irvine 的“汇编语言 x86 编程”一书学习汇编编程。
在书中,作者说
最常见的字符串类型以空字节(包含 0)结尾。称为以空字符结尾的字符串
在本书的后续部分,作者有一个没有空字节的字符串示例
greeting1 \
BYTE "Welcome to the Encryption Demo program "
Run Code Online (Sandbox Code Playgroud)
所以我只是想知道,在 x86 汇编语言中,空终止字符串和不以空终止的字符串有什么区别?它们可以互换吗?或者它们彼此不等价?
这里没有任何特定于 asm 的内容;这与 C 中的问题相同。这完全是关于如何将字符串存储在内存中并跟踪它们的结束位置。
空终止字符串和不以空终止的字符串有什么区别?
以空字符结尾的字符串0后面有一个字节,因此您可以找到以strlen. (例如用一个慢repne scasb)。这使得它可以用作隐式长度的字符串,就像 C 使用的那样。
NASM 大会 - 这个变量后面的“,0”是什么?解释了在静态存储中创建一个的 NASM 语法db。 db 在 nasm 中的使用,尝试存储和打印字符串显示当您忘记 0 终止符时会发生什么。
它们可以互换吗?
如果您知道以空字符结尾的字符串的长度,则可以将指针+长度传递给需要显式长度字符串的函数。该函数永远不会查看0字节,因为您将传递不包含0字节的长度。它不是字符串数据的一部分。
但是如果你有一个没有终止符的字符串,你就不能把它传递给一个需要空终止字符串的函数或系统调用。(如果内存是可写的,您可以0在字符串后存储 a以使其成为以空字符结尾的字符串。)
在 Linux 中,许多系统调用将字符串作为 C 风格的隐式长度空终止字符串。(即只是一个char*没有通过长度)。
例如,使用open(2)一个字符串作为路径:int open(const char *pathname, int flags); 您必须将一个以空字符结尾的字符串传递给系统调用。'\0'在 Linux(与大多数其他 Unix 系统相同)中创建名称包含 a 的文件是不可能的,因为所有处理文件的系统调用都使用以空字符结尾的字符串。
OTOH,write(2)需要一个不一定是字符串的内存缓冲区。它有签名ssize_t write(int fd, const void *buf, size_t count);。它不在乎是否有0at,buf+count因为它只查看从bufto的字节buf+count-1。
您可以将字符串传递给write(). 它不在乎。它基本上只是一个进入内核页面缓存(或进入管道缓冲区或任何非常规文件的东西)的 memcpy。但就像我说的,你不能将任意的非终止缓冲区作为路径 arg 传递到open().
或者它们彼此不等价?
隐式长度和显式长度是在内存中跟踪字符串数据/常量并传递它们的两种主要方式。他们解决了同样的问题,但方式相反。
如果您有时需要在遍历它们之前找到它们的长度,那么长的隐式长度字符串是一个糟糕的选择。循环遍历一个字符串比仅仅读取一个整数要慢得多。查找隐式长度字符串的长度是O(n),但显式长度字符串当然O(1)是查找长度的时间。(已经知道了!)。至少字节长度是已知的,但 Unicode 字符的长度可能未知,如果它是像 UTF-8 或 UTF-16 这样的可变长度编码。