assembly UTF-8被压入堆栈时是否使用与UTF-32相同的内存量?

v64noz0r  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(49)

这个问题是关于UTF-8在堆栈上占用了多少空间,因此在内存(RAM)中,如:它与UTF-32相同吗?所以这不是关于UTF-8在序列化到文件时占用了多少磁盘空间。如果试图消除歧义侮辱了你的智力,对不起。

  • 堆栈总是在RAM中。所以我放在堆栈上的任何东西都会占用RAM中的空间。

https://stackoverflow.com/questions/15433390/is-stack-in-cpu-or-ram#:~:text= Stack%20is%20always%20in%20RAM,at%20the%20top%20of%20stack。

  • 在x86上栈至少是32位,在x86_64上栈至少是64位。所以无论我把一个字节的字符还是三个字节的字符压入栈中,它们都至少占用32位内存。我想这就是UTF-32的情况,它在栈中占用32位。

How many bytes does the push instruction push onto the stack when I don't specify the operand size?
那么,当他们说UTF-32比UTF-8占用更多内存时,他们是什么意思呢?

编辑

UTF-32使用更多的内存,但今天的计算机配备了大量的内存。保存内存的压力消失了,UTF-32字符串的简单快速处理超过了增加的内存使用。使用UTF-32比任何试图通过检查字符串来保存内存的方法都更快。
https://seed7.sourceforge.net/faq.htm#unicode

iyfamqjs

iyfamqjs1#

在奇怪的情况下,你push多个独立的UTF-8编码单元(字节),是的,这将使用8字节的堆栈空间,每字节的UTF-8数据。
这是非常低效的,这就是为什么人们不以这种方式编写代码(除了一些简单的初学者使用堆栈反转短字符串的例子,作为理解push/pop的LIFO顺序的学习练习)。
如果你想在堆栈空间中存储字符串数据,你应该保留一些空间(比如一个本地char数组)并使用它,而不是将字节或双字拆包为qwords。比如sub rsp, 64+8/movdqu xmm0, [rsi]/movdqa [rsp], xmm0复制16个字节(UTF-32或UTF-8数据,不管是哪一个)。
如果你真的想使用push,你可以push qword [rdi+rcx]在push的时候一次复制8个字节,从源字符串的末尾向后计数,这样字符串在堆栈上的结束顺序就和源字符串一样。
访问数据时,可以使用mov eax, [rsp + rcx*4]表示UTF-32(或者最好是指针增量,但比例因子有助于说明寻址)。或者对于UTF-8,movzx eax, byte [rsp + rcx](如果你想把一个unicode代码点放到EAX中,用一个循环来检查多字节字符,并可能加载更多的字节)。把UTF-8的每个字节解压缩到8字节没有任何意义,并且使得有效地处理多字节字符变得更加困难。例如,使用8字节加载和BMI 2 pext来打包,并且可能使用andn/tzcnt/bzhi来找到多字节字符的结尾(高位清除的字节)并将其上方的垃圾归零。

字符串数据的正常处理方式(保持与磁盘上相同的打包方式),**对于Unicode的ASCII子集,UTF-8比UTF-32小4倍。**对于一些2和3字节重音字符但仍主要是1字节字符的西方语言,它仍然小得多。对于大多数字符在UTF-8中为3或更多字节长的语言,UTF-32不会占用更多的空间。(与UTF-32的每个双字相比,将UTF-8的每个字节扩展为8字节会使UTF-8占用更多的空间。)

在输入时转换为UTF-32,在输出时转换回UTF-8是有意义的。然后我们又回到了过去的好日子,字符有固定的大小,因此数组索引可以给予第n个字符(模Unicode恶作剧与UTF-8和UTF-16等可变长度编码分开)。这确实会增加空间使用,包括缓存占用,特别是对于西方语言。RAM很便宜,但缓存占用和内存带宽却不是。所以这并不总是最好的策略。

相关问题