Posted on 六月 10th, 2010 in 笔记 | 2 Comments »
起比VC风格的内联汇编,GCC的确实要别扭些,一开始要不看手册肯定一头雾水。
int foo = 10, bar = 15;
asm volatile("addl %%ebx,%%eax"
:"=a"(foo) //output constraint
:"a"(foo), "b"(bar) //input constraint
: //clobbered registers(ignored)
);
指令大家都明白,不过:”=a”(foo)这样的语法就古怪了。:后面的东西好像叫做约束,指明了输出和输入中用到的变量和寄存器。第一个的”=a”(foo)是输出的约束,就表示汇编执行完毕后foo=a。后面的”a”(foo)是输入的约束,表示汇编执行前的a=foo。这一来C和汇编就可以在约束下边交换数据了。
刚才这个a就是表示分配eax寄存器。
各种约束还挺多的…
| a,b,c,d |
对应eax,ebx,ecx,edx |
| S,D |
对应esi,edi |
| I |
常数 |
| q |
eax,ebx,ecx,edx中静态分配一个 |
| r |
eax,ebx,ecx,edx,esi,edi中静态分配一个 |
| m |
内存定位 |
| A |
同时分配eax和ebx,形成一64位的寄存器 |
| i |
一个编译时确定的立即数。好像ljmp指令的第一个参数就必须得是立即数,比如ljmp $0×80, $label。如果ljmp ax, $label就绘出现一个“Error: suffix or operands invalid for ‘ljmp’的错误” |
为什么要这么难看的语法呢…我猜这东西最早应该是给编译器而不是给人类设计的吧,比起VC风格的内联汇编,它可以得到更多关于变量和寄存器的信息,编译器分配起寄存器来可以心里有数,不用怕自作聪明的人类把事情都搞乱掉。
Posted on 五月 18th, 2010 in 笔记 | 2 Comments »
无论何时,只要单个资源需要在多个用户间共享,就必须处理一致性的问题。
回头想下“函数式语言无副作用适合写并发程序”之类的说法,只是在计算上的并发,对存储上的并发照样得上锁上钥匙。
win32的窗体使用handle而不是指针
一个窗体可能会被多个进程处理,也可以隐藏窗体对象的内部实现。
真空管和三极管的共性
都可以将信号放大,这一来就可以用电信号来控制开关了。就有了逻辑电路…
lua从堆栈机转到寄存器机
因为lua实现里表示值的那个结构体Tvalue是个tagged union,个头太大了(两个指针这么长)。在堆栈上push/pop一来一回吃资源,搞成寄存器机可以省些搬运。
为什么要有链接器
可以把程序分成模块。
C中结构体不可比较
因为结构体里数据对齐的空隙里面的东西可能随机的。
C++为什么不用printf
类型不安全。像cout好像是对每个内置类型都重载了一个<<操作符
x86实模式的逻辑地址
x86实模式的逻辑地址是段寄存器(如cs)里存一个基地址(16位),左移四位再加上一个16位的偏移。
为什么要这么蛋疼,因为当时的主线有20位(可寻址1mb),但是intel的寄存器只有16位。
自动机
就是根据输入自动切换状态的计算模型。不过状态有限,识别的语言(语言就是字符串的集合)是最少的。自动机可以识别的语言就叫正则语言。
给自动机加一个堆栈就是下推自动机,这样状态就可以无限了,可以识别的语言就叫上下文无关语言。
给自动机加一个随机存储,就是图灵机了。可以识别的语言就叫可判定语言。
好像刚弄明白动态作用域是怎么回事,拿个例子:
var a=0; //global
def f1():
a=1
def f2():
var a; //local
f1()
f2()
puts a
若是静态作用域,f2调用f1,f1修改全局变量a的值为1,输出1。这个多自然…
可是动态作用域就…输出0,全局变量a的值没有变化。
f2不是调用了f1么,f1不是改变a的值么…是啊,f2调用的那个f1改变的是f2那个局部变量a的值。也就是说,同一个函数在不同的环境下调用会有不同的行为。
好吧我正在纳闷为什么会有这种东西存在过…囧
Posted on 四月 11th, 2010 in 笔记 | 4 Comments »
GC多好多好就不多说了。没银弹嘛,什么好处什么坏处都了解下就好 TvT
引用计数
“穷人的垃圾收集”。实现简单,可以在对象失去引用时立即收集,不过对付不了循环引用。“立即收集”容易给人一种“高效”的印象,其实正相反,引用计数中的每个mov指令后面都必须跟着几条额外指令,引用的局部性还不好。跟各种GC算法比起来,引用计数的效率是最低的 :(
CPython是引用计数加备用的mark-sweep,(好像如果一开始就使用GC的话就没必要引入那套复杂的内存池机制了?
mark-sweep
从根(寄存器、局部变量和全局变量等)开始,遍历所有可访问的对象并标记之;再遍历所有变量,将所有没mark的对象收集。
C\C++中的GC实现大约是扫描bss段和堆栈什么的,找到全局变量和局部变量。C\C++中你不知道一块数据是指针还是一个纯洁的整数,所以只能用个is point to heap来猜它是不是指针,如果这个整数恰好是一块内存的地址,就只能“保守地”当它是指针mark掉了。保守式的GC中比较有名的就是Boehm的GC(貌似很靠谱!)。
停止-复制
这个需要额外一倍的内存空间。先将一切活动停止,遍历堆中所有可以访问的对象并将其拷贝到另个堆中,并将将原先的指针统统指向新的堆中对应的地址,完毕后继续程序的执行。
停止复制的同时也紧缩了内存,因而不存在内存碎片的问题(malloc/free在整理堆中碎片时候的各种搬运不容小觑),性能上好像要优于mark-sweep。缺点就是对空间浪费比较大(一倍啊一倍~)。
分代收集
遍历所有对象时候的停滞会比较厉害。想办法把停滞缩短到人类察觉不到吧…就有了分代收集和增量收集 TvT
分代收集基于这样的假设:
1.对象越新,生存期越短;
2.对象越老,生存期越长;
3.少有指向新对象的老对象
就把堆分成n块,对应n代的对象(三代就差不多吧)。再加个记忆表什么的记下指向新对象的老对象,以记忆表中的老对象以及活跃的变量等做根,重点照顾最新的这代就行了。
.net那CLR好像是分代的…缺点是经过多次收集,较老的代会积攒比较多的垃圾。
增量收集
增量收集好像是记住上次遍历到了什么地方,然后每次遍历一点,最后集中收集。
有个三色标记:
白色:未被访问的对象;
灰色:已经被访问过,子对象还未访问;
黑色:已经被访问过,子对象也已被访问;
然后就是性质:
当没有灰色对象时,所有的白色对象都是垃圾;
不会有黑色对象指向白色对象;
每个灰色对象都位于收集器的队列中(作为下次收集的根);
Posted on 三月 5th, 2010 in 笔记 | 8 Comments »
老师:Monad想到什么呢?
同学:毛茸茸的猫猫!
好同学们,请默念“Warm and Fuzzy”100遍~
。。
。。
。。
。
。
。
。
。
。

。
。
。
。。
。。
100遍了没。。。好,我们先看看State猫猫的类型吧 ^_^
newtype State s a = State { runState :: s -> (a, s) }
里面有个难看的record syntax,咱们无视之,改成:
data State g v = State (g -> (v, g))
就是一个lambda,外加一二元组:v表示猫猫正经计算中的值,g就表示猫猫的状态啦(就一个全局变量嘛)~那个lambda的参数g也一样。相应的猫猫Instance也就是如下:
instance Monad (State g) where
return v =
State $ \g -> (v, g)
(>>=) (State m) f =
State $ \g ->
let (v, g') = m g
(State m') = f v
in m' g'
还是一环套一环,函数编程没有变量,那就向下传递的时候改变它的值就行了。再加两个小喽骡:
get_g = State $ \g -> (g, g)
set_g v = State $ \_ -> (v, v)
全局变量的值不也在那个lambda的参数里么,get_g它设成计算中的值,这样在do-notation中就可以g <- get_g了。set_g则是把它的参数设到g里,而原先的g无视扔掉即可。
加个函数试验下:
run (State m) i = m i
add1 :: State Int Int
add1 = do {
g <- get_g;
set_g $ g + 1;
}
add3 = do {
add1;
add1;
add1;
}
进ghci输入run add3 1可得(4,4),可见那个“全局变量”就这么变化了。
回头再想想它的类型,一个二元组不就够了嘛,为什么要套那层lambda呢?试下就知道
data State g v = State (g, v)
instance Monad (State g) where
(>>=) (State (g, v)) f = (g, f v)
看着不错,接着来:
发现问题了没,return我们实现不了…搞不到原先g的值,链子就断在了这一环。解决方法就是把它推后,不是没有g么,于是放到参数里等着别人(>>=)给,这算不算惰性呢? :)
ps:明白了State是怎么回事,附一山寨parsec ^_^ http://github.com/Fleurer/FParser