选择特殊符号
选择搜索类型
请输入搜索
第一章古典建筑的遗产002
古典风格/003
古典柱式/005
多立克柱式/006
爱奥尼克柱式/007
科林斯柱式/008
希腊神庙/009
罗马风格/011
罗马拱/013
穹顶和筒形拱/014
神庙以及剧院/015
第二章拜占庭和罗马风的建筑018
拜占庭建筑/019
罗马风/021
诺曼风格/023
后罗马风建筑/025
第三章伊斯兰建筑028
倭马亚和阿巴斯/029
非洲的伊斯兰教/031
摩尔式建筑风格/033
奥斯曼风格/035
波斯建筑/037
莫卧儿建筑/039
第四章传统的亚洲风格 042
中国传统建筑/043
日本传统建筑/045
庙宇建筑/047
亚洲地区建筑风格/049
第五章哥特式以及中世纪建筑052
中世纪的奠基/053
中世纪的防御工事/055
成长为哥特式/057
法式哥特/059
英式哥特/061
意大利和德国的哥特建筑/063
欧洲中部和北部的哥特建筑/065
第六章文艺复兴及巴洛克建筑 068
文艺复兴/069
文艺复兴盛期/071
风格主义/073
都铎王朝和詹姆斯一世时期/075
巴洛克/077
英式巴洛克/079
洛可可/081
阿尔卑斯和波西米亚/083
西班牙巴洛克风格/085
地中海风格/087
低地国家/089
俄罗斯巴洛克/091
第七章新大陆094
前哥伦布时期/095
印第安人村庄/土砖/097
西班牙人的构想/099
英国殖民地建筑/101
盐盒式建筑/103
美国德裔宾州人建筑/105
震教徒建筑/107
法国殖民地:阿卡迪亚教区/109
荷兰殖民建筑/111
法国殖民地:克里奥尔及其
南部/113
非洲人的影响/115
西部本地建筑/117
西班牙殖民地/119
原木房屋/121
加勒比地区建筑风格/123
第八章古典复兴建筑126
帕拉迪奥式建筑/127
法国新古典主义/129
德国新古典主义/131
乔治亚时代的艺术风格/133
联邦制/亚当式/135
杰弗逊式/137
希腊复兴式/139
英国摄政时期/141
第九章维多利亚风格144
哥特式建筑复兴/145
维多利亚哥特式/147
古罗马建筑复兴/149
文艺复兴时期的建筑复兴/151
意大利风格建筑/153
木匠哥特式建筑/155
美洲木结构建筑/157
安妮女王式建筑/159
木瓦风格建筑/161
理查森罗马式/163
异国风情的复兴/165
美术派风格/167
城堡风格/169
第二帝国风格/171
汽船哥特式/173
城市公寓/175
都铎王朝风格的复兴/177
“铁器时代”唯物主义/179
英国工艺美术运动/181
第十章早期现代建筑184
美国的文艺复兴/185
凯尔特复兴/187
芝加哥学派/189
摩天大楼/191
草原风格/193
乡村风格/195
凉台平房/197
手工艺风格/西班牙传教会式
建筑风格/199
新艺术/201
分离派/青年风格/203
加泰罗尼亚的现代主义/205
构成主义/207
艺术装饰派:爵士时代/209
艺术装饰派:流线型/211
功能主义/213
美国风/215
包豪斯/217
国际风格/219
有机建筑(赖特)/221
第十一章战后现代建筑224
战后国际风格/225
赖特:成熟期/227
现代主义/229
粗野主义/野兽派/231
未来主义/233
表现主义/235
结构表现主义/237
当代的现代主义/239
后现代主义/241
解构主义/243
弗兰克·盖里/245
流体建筑/247
有机建筑/249
当代建筑趋势/2512100433B
对于一般人来说,一座楼就是一座楼;但是对于一个建筑观察者来说,任何一座建筑都可以代表更多东西。它可以是后现代的伟大杰作,可以是英王爱德华时代的宏伟建筑,还可以是草原风格的宅邸。它可以游走于装饰艺术领域,可以从绘画文学汲取灵感,甚至可以自己生长、拓展辐射,最终在主根系中延生出茂盛而繁复的枝蔓。在《世界建筑风格漫游:从经典庙宇到现代摩天楼》中,有心的读者会发现大量有价值的信息,覆盖了从古代建筑遗迹到乡村原木小屋再到稀有的摩天建筑等方方面面。它可以帮你认识建筑,总结建筑风格的关键词,感受设计者的思维,梳理建筑的发展脉络。《世界建筑风格漫游:从经典庙宇到现代摩天楼》不仅概括介绍一些著名的建筑,而且从细节处精确讨论同时伴有丰富而精美的照片,并用插图形象展现一些专业建筑术语,如飞檐、飞扶壁、山墙等。读者以建筑观察者的客观视角,浓绘不同的风格缩影。在这《世界建筑风格漫游:从经典庙宇到现代摩天楼》中游走天下,狩猎建筑,你会有颇丰的收获,有一天,你也会成为出色的建筑观察者。
美式乡村风格、古典欧式风格、地中海式风格、东南亚风格、日式风格、新古典风格、现代简约风格、新中式风格,如外国建筑史中古希腊、古罗马有陶立克、爱奥尼克和科林斯等代表性建筑风格,中古时代有哥特建筑的建筑风...
指建筑设计中在内容和外貌方面所反映的特征,主要在于建筑的平面布局、形态构成、艺术处理和手法运用等方面所显示的独创和完美的意境。建筑风格因受不同时代的政治、社会、经济、建筑材料和建筑技术等的制约以及建筑...
功能主义建筑 古典复兴建筑 罗曼建筑 古罗马建筑 浪漫主义建筑 现代主义建筑 洛克克风格 文艺复兴建筑 折衷主义建筑 后现代主义建筑 有机建筑
6.2建筑风格——心仪的建筑风格
6.2建筑风格——心仪的建筑风格
欧式建筑风格VS美式建筑风格
欧式建筑风格 VS 美式建筑风格 一、两大风格之间的历史背景对比 1、欧式风格的发展 欧洲建筑在大的概念上应归属于西方建筑,从古希腊时代起到 20世纪三四 十年代,欧洲一直是西方建筑文明的中心, 第二次世界大战结束后, 这个中心逐 渐偏移到了北美, 虽然有更为早期的欧洲原始建筑, 但是欧洲建筑真正的源头是 古希腊文明,公元前 5世纪到公元前 4世纪,古希腊的建筑艺术达到鼎盛, 以雅 典卫城及其神庙为代表的一个个建筑杰作横空出世,它们简单而纯净和谐而完 美,具有惊人的艺术创造力。 公元前 1世纪,古希腊人的 “光荣”被古罗马人的 “伟大”所取代,后者兴建的宫殿、 凯旋门、竞技场、剧场和大浴场雄伟壮观富丽堂皇, 他们和古希腊建筑一道被视 为垂范千古的经典成为西方建筑文化最深刻的根源。 在接下来中世纪的 1000余年中,欧洲建筑具有两大特点:一是基督教堂和 修道院始终是欧洲建筑的主体; 二是伴随
来源:MRRiddler ,
blog.mrriddler.com/2017/02/10/计算机体系-编译体系漫游/
要想让代码乖乖运行,自然代码要先经过编译,这篇文章就来聊聊编译体系。
代码的编译过程分为四个阶段,预处理、编译、汇编、链接。而编译阶段是整个过程中最复杂的阶段,编译阶段还可以分为词法分析、语法分析、语义分析。
在一头扎进这四个阶段之间,先聊一下语法、语义。人类之所以能在进化的历史长河中,成为动物中的佼佼者,进化出的复杂的沟通机制—语言功不可没。假如,我说出这句话:你个产品狗还在改需求!那么语法是啥呢?简单说就是构成这句话的顺序,假如顺序错乱意思就不同了。那么语义是啥呢?就是语境,根据我说这句话的情景,才能解释出你指的是谁。语法在编程语言中,表现出来的就是语法结构和结合律。语义表现出来的就是上下文(context)。
预处理(Preprocess):处理预处理符(#),包括宏展开、头文件引入。 词法分析(Lexical Analysis、Tokenizer):写出的代码实际上就是字符串,此阶段需要对字符串进行扫描(Scanner),将字符串扫描出分析的最基本单位(token),并在扫描过程中将它们分类,此阶段是没有任何语义的。也可以理解成将代码扫描出基本表达式。 语法分析(Syntactic analysis、Parser):生成AST抽象语法树,检查语法结构,此阶段是上下文无关的。也可以理解成将基本表达式按语法结构组合成复合表达式。 语义分析(Semantic Analysis):语义检查(比如检查浮点数乘以指针,虽然语法结构正确但是语义检查不合格),将程序与上下文结合,进行静态类型分析,确定AST每个节点的类型。也可以理解将复合表达式结合环境(Environment),并且确定基本表达式、复合表达式的类型。 中间码(Intermediate Representation):与语言无关、平台无关的中间码。如果编译器面向多语言,对于任意语言编译阶段后可以生成通用的中间码,这样编译器就有多语言的高拓展性了。生成中间码后再交给汇编阶段,再生成与平台相关的汇编,这样使编译器将平台相关性尽量往后推移。中间码除了做为“桥接“,对中间码的优化也是整个编译过程中的关键优化。 汇编(Assemble):对中间码生成平台具体的汇编,在这个阶段添加对多个平台的支持,编译器就可以跨平台了。最后生成机器码。 链接(Link):将每个机器码编译单位中引用的其他编译单位中的变量、函数符号修正(fix)成真实地址。编译历史
编译的历史基本就是计算机的进化史,是很有趣的一段故事。Long time ago… 程序员写程序都是用纸带,那时候还在写0、1机器码。纸带上打孔就是0,不打孔就是1。然后计算机读取纸带就是读取指令。但是就像互联网本质就是提高效率一样,这样写程序的效率怎能接受?并且,写程序如果犯了错误怎么办?重新从头到尾再用新纸带搞一遍?程序员们机智的开始想办法了,先是这样搞:
将指带有误的地方,用黑黑的小贴纸填上去,这样将0改成1了。这也是Patch名字的由来。但是这样写指令效率还是太低,程序员们再机智的想办法。后来将指令进行符号化(Symbol),抽象出指令集,这时就出现了汇编,程序员的效率上了一个档次。但是新的问题又出现了。在写过程调用的时候,要写jmp 具体的函数地址。如果后来要在被调用的函数前面添加指令,那么函数地址也要跟着改。这样牵一发动全身的感觉可不好,为了让影响(impact)缩减到最小,不如将函数地址也符号化。凡是写过程调用先写成jmp func,等到程序生成机器码的时候,再将func换成真正的函数地址,这一步也就是将程序员手动修正交由汇编器修正。
随着生产力的提升,程序的规模越来越大,新的问题出现了,程序膨胀到难以维护和阅读了。程序员们就将程序模块化、层次化。这样也使编译的单位更小粒度化。编译的时候,不同编译单位之间的细节是互相隔离的。比如,对于C语言系,一个.h和一个.m就构成了一个编译单位。.m汇编时,是不知道其他.m的全局变量、函数地址的,而调用的时候就只能用符号进行调用,等到最后所有.m都生成机器码后再进行统一的修正。而负责这一步的就是链接器(Linker),这一步也叫重定位(Relocation)。
目标文件
经过汇编这一阶段后,就会生成目标文件。目标文件和可执行文件已经非常相近了,只是有些符号还未修正,结构上会进行调整。Windows平台下为PE(Portable Executable),Linux平台下为ELF(Executable Linkable Format),Mac平台下为Mach-O。虽然不同平台都有自己的格式,但是它们实际上都大同小异。下面大体聊一下文件的实际字段,这些知识会为后面我们搞一些符号重绑定做铺垫。
section
首先,文件分段(section)。不同的Section放置不同的信息,文件还有一个section header table放置控制信息。实际上,就类似图片格式和mutipart的HTTP报文。以下是一个ELF目标文件的常见section:
—— —— —— —— —— —— ——
|header | -----> 文件头
|—— —— —— —— —— —— ——|
|.text | -----> 代码段
|—— —— —— —— —— —— ——|
|.data | -----> 已初始化全局变量、静态变量
|—— —— —— —— —— —— ——|
|.bss | -----> 未初始化全局变量、静态变量
|—— —— —— —— —— —— ——|
|other sections... |
|—— —— —— —— —— —— ——|
|section header table| -----> section控制信息表
|—— —— —— —— —— —— ——|
|.strtab | -----> 字符串表
|—— —— —— —— —— —— ——|
|.symtab | -----> 符号表
|—— —— —— —— —— —— ——|
|..... |
—— —— —— —— —— —— —— —
.text放置代码,.data放置已初始化的全局变量和静态变量,.bss放置未初始化的全局变量和静态变量。为什么代码和全局变量、静态变量要分开放?实际上,这就是个等同性问题。代码段就是可读的数据,而全局变量、静态变量是可读可写的数据。如果有多个进程进行同一份代码,这些代码都是等同的,不需要各自复制一份。而全局变量、静态变量是不等同的,需要各自复制一份。而分什么又要分已初始化、未初始化呢?目标文件未初始化的全局、静态变量只需要放置一个占位符,代表其在.bss。而.bss在链接阶段,变量不占空间,在装载时由操作系统再分配空间。可以看到,既然是文件格式,不管怎么设计,主要的目的就是占更少的空间。
header有很多文件控制信息,就不一一表述了,其中最重要的就是记录了section header table的起始地址。而section header table记录了所有section的名字、类型、长度、在文件中的偏移量(offset)等。如果想要寻址到任意section都要通过这个header table。section header table实际上是由struct构成的数组。
.strtab放置section名、变量名,包括符号名的字符串。由于在整个结构中,字符串的长度是不定的,一般将这些字符串统一放置在一个table中,然后存储table中的offset,最后寻址到字符串。比如,在下表中,我想找到girlfriend一词,我只要拿到.strtab的base地址,加上girlfriend的offset 9就可以找到这个字符串。
0 1 2 3 4 5 6 7 8
i 0 w a n t 0 a 0
g i r l f r i e n
d
.symtab就是大名鼎鼎的符号表。每个目标文件都有自己的符号表,符号表记录符号的映射,符号可以这样分:文件外符号和文件内符号,文件外符号就是使用在其他文件定义的符号,文件内符号除了在文件内定义给其他文件使用的符号,还包括每个section符号,在文件内定义光是文件内使用的符号。光文件内使用的符号,对链接没有帮助,主要为了崩溃后分析而存在。符号表也是一个由struct构成的数组。ELF的32位符号sturct:
typedef struct {
int32_t st_name;
uint32_t st_value;
int32_t st_size;
unsigned char st_info;
unsigned char st_other;
uint16_t st_shndx;
} ELF32_Sym;
st_name字段就是符号的名字,表示为在.strtab中的字符串offset。st_info表示是局部符号、全局符号还是弱符号。符号也可以分为强符号(Strong Symbol)、弱符号(Weak Symbol),顾名思义,强符号有唯一性,弱符号没有唯一性,一个强符号可以和多个弱符号共存,多个重复的强符号不可以共存,链接器会报出duplicate dymbol,可以用attribute((weak))指明弱符号。相对的,符号也有强引用(Strong Reference)、弱引用(Weak Reference),在链接进行符号修正的时候,强引用必须修正,而弱引用可以不修正,可以用attribute((weakref))指明符号弱引用。
st_shndx字段指明了符号是文件外符号,还是文件内符号。如果是文件外符号就为SHN_UNDEF。如果是文件内符号包括给其他文件使用的、光自己使用的、section符号,就为所在section的索引号,而st_value表示所在section的offset。等到链接过后,不管是文件外符号还是文件内符号,st_value指明实际地址。
符号修饰(Symbol-Decoration)与函数签名(Function-Signature)
机智的同学已经发现了,如果光按上面聊的方式进行符号链接是有问题的,假如目标文件有个func符号又引用了其他文件同名的func符号,那符号不就出现冲突了?这里就需要引入函数签名,函数签名是一个函数的名字、参数类型、所在类名组成的字符串,不同语言、不同编译器对同一个函数生成的函数签名是不一样的,比如OC中函数签名还要加上返回变量类型,C++中还要加上NameSpace。在链接的时候,过程调用符号不光是函数名,是对函数签名处理后的结果,全局变量符号也是经过类似用函数签名处理后的结果。这一处理过程就是符号修饰。
fishhook
fishhook是facebook开源的重绑定Mach-O符号的库,最常用来hook C语言函数,而且实际上只能重新绑定C符号,因为符号修饰这一步只去掉了”_”,相当于只针对C语言做了符号修饰。在了解了目标文件后,重绑定就不是那么困难了。最基本的思路就是先拿到header,然后通过header拿到section header table,再找到.hash,.hash是一个用于加快访问.symtab的哈希结构,再索引到.symtab,详见这里,通过name去.strtab比对符号名,如果匹配就置换value。
https://docs.oracle.com/cd/E2382401/html/819-0690/chapter6-48031.html
fishhook大体实现原理就是这样,只不过对Mach-O平台特性改进一下方案就行。在Mach-O中类似于section header table的段叫做load commands。并且Mach-O中使用二级命名空间,先分segment,就相当于上文中的section,然后再在同一segment中区分section。
先拿到header,通过header中的ncmds(segment的个数)和cmdsize(segment的大小)字段就可以找到所有的segment。然后找到.strtab、.symtab、indirect symbol table。这个indirect symbol table是一个uint32_t的数组。它就是nl_symbol_ptr(non-lazy)和la_symbol_ptr(lazy )对应的.symtab struct数组的索引。nl_symbol_ptr和la_symbol_ptr section section中的reserved1字段指明对应的indirect symbol table起始offset。只要从这两个section对应的indirect symbol table起始表项再跳到.symtab去匹配、置换就可以了。
下面是32位下.symtab的struct,可以看到和上段文章讲的几乎一致:
struct nlist {
union {
char *n_name; /* for use when in-core */
uint32_t n_strx; /* index into the string table */
} n_un;
uint8_t n_type; /* type flag, see below */
uint8_t n_sect; /* section number or NO_SECT */
int16_t n_desc; /* see <mach-o/stab.h> */
uint32_t n_value; /* value of this symbol (or stab offset) */
};
上文提到的Mach-O格式如下:
—— —— —— —— —— —— ——
|header |
|—— —— —— —— —— —— ——|
|load commands |
|—— —— —— —— —— —— ——|
|__Text |
|—— —— —— —— —— —— ——| —— __nl_symbol_ptr
|__Data | -----> |
|—— —— —— —— —— —— ——| —— __la_symbol_ptr
|other sections... |
|—— —— —— —— —— —— ——|
|.strtab |
|—— —— —— —— —— —— ——|
|.dynsym | -----> indirect symbol table
|—— —— —— —— —— —— ——|
|..... |
—— —— —— —— —— —— —— —
更加详细的格式,推荐这篇文章。
http://turingh.github.io/2016/03/07/mach-o文件格式分析/
链接
上面聊了这么多 ,那静态链接到底是如何将多个目标文件链接成一个可执行文件的呢?
静态链接分为两阶段(Two-pass Linking),第一阶段先扫描所有目标文件,调整结构。将所有目标文件相同section合并,包括.symtab合并成全局.symtab,然后为每个section分配虚拟地址,再将全局.symtab中的符号进行置换成虚拟地址。
这里如何将全局.symtab中的符号置换成虚拟地址呢?实际上,在分配section虚拟地址后,符号的虚拟地址按所在section虚拟地址加offset就可以计算出了。
第二阶段将所有符号进行修正。通过重定位表找到所有section中需要被修正的符号位置,然后从全局.symtab查询出虚拟地址置换。
每个section都会对应一个重定位段,这些重定位段组成一个重定位表。每个重定位表项叫做重定位入口(Relocation Entry),它记录了所需重定向符号所在段的offset。
静态链接库
静态链接库就是一组目标文件,经过压缩、索引而成的一个文件形式。当我们平时在使用静态链接库的时候,实际上链接器会根据所需的符号,在库中搜索到相应的目标文件,并将其链接入最终可执行文件。
动态链接
随着静态链接慢慢发展起来,静态链接也暴露出了问题。静态链接将链接与被链接的目标文件结合的太紧密了,导致如果多个目标文件要链接同一个目标文件,那这个被链接的目标文件相当于要被复制多份,每个可执行文件都要包含这个被链接的目标文件的内容,这样会占太多冗余空间。那怎么办?将链接与被链接的目标文件先隔离开,将链接的时机往后推移,等到装载的时候再进行链接。这样,让被链接的目标文件只占一份空间就好。
既然动态链接隔离开了链接、被链接目标文件,链接目标文件需动态链接的符号,就需要先做个动态链接占位符。这也就是说,在目标文件链接成可执行文件时,即使是用作动态链接的目标文件也要作为动态链接库输入到链接阶段,以供目标文件识别哪些符号是动态符号。
动态链接重定位
上面已经聊完了在链接阶段对静态链接进行重定位,根据符号所在section的虚拟地址和所在section的offset。而动态链接可以这样重定位吗?不行,这时动态链接库的地址还没有确定,必须等到装载以后操作系统分配。那可以等到装载以后,确定地址后再直接进行重定位吗?不行,假如动态链接库被多个进程引用,装载时动态链接库进行重定位,动态链接库映射到每个进程中的虚拟地址都不一样,动态链接库只能对一个进程重定位,那么动态链接库就不是共享的了。那怎么搞?
通过.got(global offset table),.got就是一个指针数组,.got存储引用符号的实际地址。而代码段引用符号直接更改为引用.got项的位移,这在链接阶段以后就不会再改变了。然后将.got分配在.data section,装载时每个进程复制一份并修正。实际上,动态链接重定位指的就是在装载的时候,根据全局符号表修正.got表项。动态链接库使用全局变量、静态变量、引用文件外过程调用都要经过.got。.got就像indirection table一样,解决多进程共享动态链接库。
这样,动态链接库虽然在不同进程中有不同的映射虚拟空间,但物理空间上共享。.got在不同进程中,虚拟空间和物理空间都不共享。如下图所示:
virtual address -> physical address
—— —— —— —— —— —— ——
|processA |
|—— —— —— —— —— —— ——|
|..... |
|—— —— —— —— —— —— ——|
|dynamic libiraries |----------
|—— —— —— —— —— —— ——| |
|..... | | |..... |
|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|
|.got |---------|---------->|.got |
|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|
|..... | | |..... |
|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|
----------->|dynamic libiraries |
—— —— —— —— —— —— —— | |—— —— —— —— —— —— ——|
|processB | | |..... |
|—— —— —— —— —— —— ——| | |—— —— —— —— —— —— ——|
|..... | | ------>|.got |
|—— —— —— —— —— —— ——| | | |—— —— —— —— —— —— ——|
|dynamic libiraries |---------- | |..... |
|—— —— —— —— —— —— ——| |
|..... | |
|—— —— —— —— —— —— ——| |
|.got |---------------
|—— —— —— —— —— —— ——|
|..... |
|—— —— —— —— —— —— ——|
动态链接库文件外符号重定位用.got就搞定了,那动态链接库文件内符号呢?静态链接同样是在链接阶段重定位就搞定了。动态链接将绝对寻址指令更换成相对寻址指令,只要指令的offset不变,相对寻址指令就可根据当前地址和offset得到正确的地址,这样文件内符号根本不需要重定位了。基于以上两点的处理,代码段在链接后就不需要更改了,这样的代码段也叫做地址无关码(PIC),也就是说代码段和装载后的地址无关。
延迟绑定(PLT)
由于要跳过.got引用动态链接库的符号,动态链接库比静态链接库慢5%左右,但相比于节省的大量空间还是很划算的。除此之外,动态链接还会有其他的问题,装载时需要进行重定位,会导致性能下降。不如,直接延迟绑定,等到过程调用符号运行时被用到再进行重定位。
整个过程强烈推荐这篇文章,要想理解动态链接重定位,没有比追汇编更好的方法了。动态链接和延迟绑定整个过程都是由动态链接器帮我们完成的。当引用符号(callq)时,先jmpq去plt结构,使用了PLT,引用符号就要先jmpq去plt结构。如果没找到相应的地址,然后再jmpq去.got.plt或.got中。再把符号相应.rela.plt表中的索引和.got.plt相应的表项,pushq入栈,rela.plt中有符号的类型和名字。再jmp到动态链接库中(_dl_fixup),去全局符号表中找到符号相应的地址。再将地址reloc到.got.plt或.got相应表项。然后就完成了延迟绑定,下次引用同样的符号就可以jmpq去plt结构找到地址。
http://sysfork.com/post/linux-dynamic-lib-lazy-load/
引用
程序员的自我修养—链接、装载与库关注「ImportNew」,看技术干货
《计算机建筑漫游实例(附光盘)》共九章。内容有:建筑漫游动画基础知识、Premiere软件学习、室内一楼建模、室内二楼建模、住宅小区室外建模、住宅小区游览等。
当您出差在外地时,您可以在任何一台有互联网连接的电脑上,登陆到自己的传真服务器上,实现您漫游查看传真的功能。2100433B