2006年7月24日星期一

考研班

这段时间上考研复习班,每天早上7点钟起床,晚上7点钟才能回到宿舍,真是很累。不过好歹也养成了一天三顿饭的正常习惯(原来都是一天一顿……汗)。中午也很难好好的休息一下,教室的环境比较恶劣。还是能充分地感受到当时高考时候的那种氛围,每个人都在为了一个考试努力奋斗,为了考上一个好的研究生院而奋斗,而我在中间就感觉像是一个异族,和高考一样,对这一切都放不开,自己明明不愿做,但对这一切有都不愿真心实意地投入,这种心态和准备TOEFL和GRE确实还是不同的。现在还是存有疑虑,怕两头都抓,到头来两头都抓不住啊。

后天就结束了,可以回家啦!

2006年7月9日星期日

C 与汇编代码结合

花了近一个星期,研究了一个看起来初级得不能再初级的问题,刚才终于成功了。就是用汇编写一个函数,导出到一个 C 程序里面调用它。想得很简单,不外乎就是 .asm 和 .c 分别编译成 .obj,然后链接。谁知问题多多。

汇编我用的是 NASM (http://sourceforge.net/projects/nasm),代码如下,实现一个类似 memcpy 的函数(myMemcpy.asm):

global _myMemcpy

;segment myMemcpy class=code

_myMemcpy:
mov eax, esp
push cx
push ds
push es

mov cx, [ss:eax + 12] ; count
mov ds, [ss:eax + 10] ; src segment
mov si, [ss:eax + 8] ; src offset
mov es, [ss:eax + 6] ; dest segment
mov di, [ss:eax + 4] ; dest offset

xor eax, eax
mov dx, es
mov ax, di ; return value is in dx:ax

rep movsb

pop es
pop ds
pop cx
retf

返回值存于 dx:ax。

C 代码如下,用 Turbo C 2.01 编译(test.c):

#include >stdio.h<
#include >stdlib.h<

extern void* myMemcpy(void* dest, void* src, int count);

main()
{
const int c = 5;
char* a = (char*) malloc(c);
char* b = (char*) malloc(c);

sprintf(a, "Dest");
sprintf(b, "Src");

printf(myMemcpy(a, b, c));

return 0;
}

如果运行正确,则会输出 Src。

NASM 汇编语句为 nasmw myMemcpy.asm -f obj,没什么好说的。

C 编译语句为 tcc -mh -c test.c,此处的 -mh 表示选择 Huge 内存模型,而其他的内存模型都不可行。如果用 Small 或者 Tiny 模型会产生错误:

Fixup overflow in module TEST.C at _TEXT:0036, target = _MYMEMCPY

原因可参见 Coping with 'Fixup Overflow' messages.,而 Large 模型(-ml)会在程序结束前的一个 call 产生错误,错误代码 36。

链接语句为 tlink /x test.obj myMemcpy.obj lib\c0h.obj, , , lib\ch.lib ,c0h.obj 和 ch.lib 对应 Huge 模型的库文件。

如果在 myMemcpy.asm 没写 segment 语句,NASM 会自动把 _myMemcpy 分配到 __NASMDEFSEG 段里去。segment 语句后面的 class=code 会告诉链接器,这个段一个代码段。可以在链接时把 /x 改成 /s,生成详细的 map 文件,里面记载了每个段的类型。当然,这个 segment 语句不是必须的。

关于外部函数的声明,Coping with 'Fixup Overflow' messages. 里面提到可以写成

extern void (far * far myMemcpy)(void* dest, void* src, int count);

这样,产生的代码(可由 tcc -S test.c 产生)为

mov ax,seg _myMemcpy
mov es,ax
call dword ptr es:_myMemcpy

而一般的声明方式产生的代码是

call far ptr _myMemcpy

两种方法我都试过,不过似乎只有一般的 call far ptr _myMemcpy 可以正常运行,也不会产生任何链接错误或者警告。简单才是美嘛。

我这里生成的 exe 文件,程序的实际入口是在相对入口地址偏移 F8 的一个 call,用 W32Dasm 打开可以发现那是 call 0000:0000,也就是在 call 前的代码运行时修改了这个 call 的实际目标地址。而 call 里面的代码就和 tcc -S test.c 生成的 test.asm 类似了。

虽然简单的一个小程序,但遇到问题还是折磨死人。不过也好,幸亏有这些问题,我也学到很多关于系统底层、可执行文件和调试方面的知识。

2006年7月8日星期六

夜思

自习回宿舍,夜阑人静,耳闻贝多芬的钢奏,信步所至,百感交集。忽然想到,这奇妙无比的感觉虽然现在就在我身上,这无可替代的享受虽然现在还属于我,但它决不会永远地持续下去,即使我现在就站在原地依依不舍,夜阑总会被白昼驱赶,人静总会被秩序打破。这享受也只能属于我一个人,不可能同另一个人,另一个女人,共同拥有和品味。想到这里,本欲放声痛哭,奈何无泪可出。抬头望月,回想这三年半独立的生活和种种遭遇,还不如一个释怀的苦笑来得痛快。行至湖边,希望拥有一架钢琴、希望能自己来创造快乐的信念越来越强烈,挥之不去。

虽然音乐绝不是一个人唯一的快乐源泉,虽然肉体一样需要得到满足……

回到宿舍,又是一片乌烟瘴气。

2006年7月1日星期六

《忏悔录》读后

一个多月没更新了,GRE 和期末考试是主要原因。同原来一样,在最忙的时候还是忍不住去找了一本书来读。上次在厦门的书店就看到了这本《忏悔录》,回来就在图书馆借了回来。

今天晚上刚看完了第二部,总的来说有两点感想:

1) 世上没有毫无道理的无理取闹。从书中的注解和安德烈•莫洛亚为1949年法国勃达斯版的《忏悔录》写的序言中看,卢梭在他的作品中所表达的很多疑惑和指控其实都是缺少根据的。而他所不能理解的百科全书派的朋友们变成了他的敌人,他自己的所作所为在其中所占的地位也应该是不可忽略的,如安德烈•莫洛亚所写到的,“他,一个聪明的公民,一个与道德为伍的朋友,一个对不纯洁的享乐的蔑视者,一个文明的敌人,征服了巴黎。接着,这个戏剧的反对者却为宫廷写了一部歌剧。…… 这位发表最著名的教育论文的作者却把自己的五个孩子全送进了育婴堂,或者至少还为此而夸耀。他就这样给自己的敌人提供了致命的武器。” 即使安德烈•莫洛亚的论据中也有言过其实的部分,卢梭所宣扬的和所做的还是反映出了很大的矛盾之处,而这可能正是他的朋友们所不能容忍的。我想,但我自己的朋友对我的态度有所改变而我又有所发觉的时候,我应该首先在自己身上找原因,虽然这往往是一项异常困难的任务。

2) 从这本书里面,我至少认识到,从小学开始就如雷贯耳的这些伟人的名字,他们的主人在真实的生活中却和任何一个有血有肉的普通人一样,有虚荣,有胆怯,有错误,有斗争。卢梭,这个自由的坚定守护者,教育理论的提倡者,竟也是一个多愁善感的、没有亲手抚养过孩子的人;狄德罗,被称为“哲学家”的哲学家,被卢梭认为是搞阴谋的人;而伏尔泰,不仅是卢梭对他怀有无法和解的憎恨,迟到了几十年的莫扎特对他毫无好感,即使他是法国启蒙运动的主要人物。时间就是一个大的筛子,会把(它认为)应该被人记住的人留下来并且美化他,把其他的人都抛进历史的长河中。一个人真正的面目往往和我们能够了解到的是迥异的。