baitang36 发表于 2020-9-18 15:42:15

【原创】list在内存中的存储方式研究

本帖最后由 baitang36 于 2020-9-18 16:04 编辑

试验程序源码:
(DEFUN TT()
(setq Group1 (list 4294967295 88888888"ABC" 3.1415926535897932384626433832795028841971 ))
(SETQ A "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
(setq Group2 (cons A Group1))
)
编译后解码:
Offset      01234567   89ABCDEF
00000000   0D 0A 20 46 41 53 34 2D46 49 4C 45 20 3B 20 44      FAS4-FILE ; D
00000010   6F 20 6E 6F 74 20 63 6861 6E 67 65 20 69 74 21   o not change it!
00000020   0D 0A 34 39 0D 0A 31 3020 24 14 00 00 00 00 09   4910 $      
00000030   09 00 33 38 56 4C 05 0908 00 09 07 00 35 04 06   38VL       5
00000040   00 03 06 05 00 09 04 0006 03 00 03 03 00 03 05                  
00000050   00 35 02 02 00 03 0B 0601 00 16 24 0D 0A 32 30    5         $20
00000060   39 20 34 20 24 14 01 0101 00 32 00 32 18 2A 39   9 4 $   2 2 *9
00000070   01 00 5B 54 54 00 00 0101 43 00 00 03 00 0A 32   [TT    C   2
00000080   00 32 31 2A 39 01 00 5B47 52 4F 55 50 32 00 43    21*9[GROUP2 C
00000090   4F 4E 53 00 41 00 00 5501 00 34 00 41 41 41 41   ONS AU4 AAAA
000000A0   41 41 41 41 41 41 41 4141 41 41 41 41 41 41 41   AAAAAAAAAAAAAAAA
000000B0   41 41 41 41 41 41 41 4141 41 41 41 41 41 41 41   AAAAAAAAAAAAAAAA
000000C0   41 41 41 41 41 41 41 4141 41 41 41 41 41 41 41   AAAAAAAAAAAAAAAA
000000D0   5B 47 52 4F 55 50 31 004C 49 53 54 00 00 3B 33   [GROUP1 LIST;3
000000E0   2E 31 34 31 35 39 32 3635 33 35 39 00 55 01 00   .14159265359 U
000000F0   03 00 41 42 43 3B 34 3239 34 39 36 37 32 39 35   ABC;4294967295
00000100   2E 30 00 5C 00 00 43 0000 0A 00 0A 5C 00 00 32   .0 \C   \2
00000110   00 5B 54 54 00 00 3A 0143 03 00 01 00 1C 14 01    [TT: C      
00000120   00 00 00 09 02 00 0A 5700 00 00 00 09 03 00 06          W      
00000130   01 00 09 01 00 16 18 008E AC 96 6F 83 6F 56 2A         幀杘僶V*
00000140   0A 3B 66 61 73 34 20 6372 75 6E 63 68 0A 3B 24    ;fas4 crunch ;$
00000150   3B 41 39 2F 31 38 2F 3230                        ;A9/18/20

可以看到9个字符串。
09 / 4294967295.0
08 / "ABC"
07 / 3.14159265359
06 / LIST
05 / GROUP1
04 / "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
03 / A
02 / CONS
01 / GROUP2
加载运行一下
命令: (tt)
("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 4.29497e+009 88888888
"ABC" 3.14159)

在内存中可以找到程序代码和变量地址
变量地址:
38 CF AD 13 ;函数地址表
F8 D2 B2 13 ;GROUP2
38 22 6D 0E ;CONS
C0 54 6F 0E ;A
D8 29 B4 13 ;"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"   
E0 D2 B2 13 ;GROUP1
08 3B 6D 0E ;LIST
C8 52 9F 11;3.14159265359
F8 29 B4 13;"ABC"
D8 52 9F 11;4294967295.0
程序代码如下:
14 00 00 00 00;函数开头
09 09 00 33 38 56 4C 05 09 08 00 09 07 00 35 04 06 00 03 06 05 00
;(setq Group1 (list 4294967295 88888888"ABC" 3.1415926535897932384626433832795028841971 ))
09 04 00 06 03 00 ;(SETQ A "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
03 03 00 03 05 00 35 02 02 00 03 0B 06 01 00 ;(setq Group2 (cons A Group1))
16 ;结束         
      
GROUP1的存放地址是 13B2D2E0
看一下这个地址有什么
13B2D2E0: 84 2E 4F 0E 00 00 00 00 04 00 B2 13 B8 B9 AD 13 08 77 B4 13 00 00 00 00
分行看一下
84 2E 4F 0E ;symbol mark
00 00 00 00 ;
04 00 B2 13 ;未知
B8 B9 AD 13 ;地址
08 77 B4 13 ;存放名称
00 00 00 00 ;
再看一下地址13adb9b8
13ADB9B8: D0 0C 4F 0E 00 00 00 00 D8 52 9F 11 A8 B9 AD 13
D0 0C 4F 0E;cons mark
00 00 00 00;
D8 52 9F 11;
A8 B9 AD 13;下一个cons地址
地址119f52d8的内容
119f52d8: 04 4D 4F 0E 00 00 00 00 00 00 E0 FF FF FF EF 41
04 4D 4F 0E;lnode mark
00 00 00 00
00 00 E0 FF FF FF EF 41;浮点数 4294967295.0
研究了一下,41EFFFFFFFE00000就是浮点数 4294967295.0的16进制编码
13ADB9A8:D0 0C 4F 0E 00 00 00 00 71 AC 98 0A 98 B9 AD 13 ;8888888
D0 0C 4F 0E ;cons mark
00 00 00 00
71 AC 98 0A ;8888888
98 B9 AD 13 ;下一个cons地址
0x0A98AC71=177777777
(177777777-1)/2=88888888
13ADB998: D0 0C 4F 0E 00 00 00 00 F8 29 B4 13 88 B9 AD 13 ;"ABC"
13B429F8: B0 56 4F 0E 00 00 00 00 9E FF C0 13 06 00 00 00 ;"ABC"
B0 56 4F 0E ;lnode mark
00 00 00 00
9E FF C0 13 ;字符串地址
06 00 00 00 ;长度*2
13ADB988: D0 0C 4F 0E 00 00 00 00 C8 52 9F 11 00 00 00 00 ;3.14159265359
注意这里的结尾是00 00 00 00,而不是下一个cons的地址了,这说明是最后一个cons
119F52C8: 04 4D 4F 0E 00 00 00 00 EA 2E 44 54 FB 21 09 40
04 4D 4F 0E ;lnode mark
00 00 00 00
EA 2E 44 54 FB 21 09 40
;400921FB54442EEA 表示浮点数3.14159265359
GROUP2的地址是13b2d2f8
13b2d2f8: 84 2E 4F 0E 00 00 00 00 04 00 B2 13 C8 B9 AD 13 18 77 B4 13 00 00 00 00
84 2E 4F 0E ;symbol mark
00 00 00 00 ;0
04 00 B2 13 ;未知
C8 B9 AD 13 ;地址
18 77 B4 13 ;名称 GROUP2
00 00 00 00 ;0
13adb9c8: D0 0C 4F 0E 00 00 00 00 D8 29 B4 13 B8 B9 AD 13
D0 0C 4F 0E ;cons mark
00 00 00 00 ;0
D8 29 B4 13 ;
B8 B9 AD 13 ;下一个地址
13b429d8:B0 56 4F 0E 00 00 00 00 69 FF C0 13 68 00 00 00
B0 56 4F 0E ;lnode mark
00 00 00 00
69 FF C0 13 ;字符串地址
68 00 00 00 ;长度*2
13c0ff69: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
这是变量A那一长串AAAAAAAAAAAAAAAAAAAAAA
13adb9b8: D0 0C 4F 0E 00 00 00 00 D8 52 9F 11 A8 B9 AD 13
这里与GROUP1的cons是相同的地址,后面的也是GROUP1的内容了。
就是说直接利用了GROUP1,没有使用新的内存,是非常节省的。

结论,
整数在内存中直接存储,表示方法是2n+1,88888888在内存中是177777777,也就是0x0A98AC71
浮点数直接编码成16进制数值,400921FB54442EEA 表示浮点数3.14159265359
小数点后位数很多时被截去,精度有一定限制。
大整数直接被编译成了浮点数。41EFFFFFFFE00000就是浮点数 4294967295.0的16进制编码。
list在内存的表示方法:开头是一个symbol表,占用24个字节。
symbol格式如下:
84 2E 4F 0E ;symbol mark
00 00 00 00 ;0
04 00 B2 13 ;未知
C8 B9 AD 13 ;存放内容,cons的开始地址
18 77 B4 13 ;存放名称 GROUP2
00 00 00 00 ;0
里面有list的名称,有cons的开始地址。
list的内容是用多个cons表示的,它组成一个链表。
cons的格式如下:
D0 0C 4F 0E ;cons mark
00 00 00 00 ;0
D8 29 B4 13 ;内容
B8 B9 AD 13 ;下一个地址
每个cons占用16个字节,开始是cons mark,后面跟着一个0或2,意思暂未知,再后面是内容。
内容有的用lnode存储,也有的用cons存储。
最后四个字节是下一个cons的地址。
最后一个cons没有下一个地址,用00 00 00 00表示这个链表结束。

clinber 发表于 2020-9-18 15:53:22

:D:D:D:o:lol

664571221 发表于 2020-9-18 16:24:41

牛逼死了......

mokson 发表于 2020-9-19 08:17:31

潜入内部看本质。太强悍了吧。

正能量的一诺 发表于 2023-2-24 08:54:23

会不会被别有用心之人利用?

baitang36 发表于 2023-2-24 09:11:46

正能量的一诺 发表于 2023-2-24 08:54
会不会被别有用心之人利用?

能怎么用?自己做一个acad?
页: [1]
查看完整版本: 【原创】list在内存中的存储方式研究