GObject 好文搜集

我个人并没有全看过,看过也不一定完全懂,有问题请去相关页面留言问原作者。

以下是 is-Programmer.com 大牛写的

当你把以下文章完全看透,你就可以说你已经会 GObject 了(不仅仅是入门)。

Tiger Soldier 写的:

《探索 GObject(1):封装》

有点可惜的是第二篇无限延长了。。 话说这是 is-Programmer.com 上第一篇有关 GObject 的文章。

Tiger Soldier 是 OSD Lyrics 的作者。

pingf 写的:

《恶心的GObject[Part I][v0.1]》

文题虽稍显不雅,但内容很好,甚至是联系源代码的。有点可惜的是第二篇还是没出来。

pingf 是 OOC-GCC 的作者。

过眼云烟写的:

《对g_signal_new()参数的解释》

《使用 Boxed Type 机制包装 C 语言结构体

《在 GObject 中使用接口》

Garfileo 的 GObject 系列文章,因为他自己已经给出了目录,我就不多嘴了:

《GObject 学习笔记汇总》

有点可惜的是没有 PDF 版离线阅读……

Garfileo 是尚未面世的 Cikada 的作者。

站外链接

GNOME 官方的 GObject 手册。别人都说很老了,也很晦涩, Garfileo 说你能完全看懂里面的 Concepts 的话,就不用看他的文了。

Wikipedia 的 GObject 介绍

GObject对象系统》。很简单的入门文,不过似乎并不完全参照以上文所述的方法。

以下是 Ubuntu Tweak 作者 TualatriX 所翻译的官方手册:

GObject参考手册:序

1、概念:GObject 的开发背景

2、GLib 动态类型系统

3、GLib 的一些规范

4、不可实例和不可类化的类型

5、可实例化的类型:对象

6、不可实例的类型:接口

7、基类:GObject

8、GObject的内存管理

9、GObject的对象属性

10、GObject的消息系统:Closure(这个是叫闭包吧?)

开始学习吧!

bsdman —— linux下看freebsd的手册页

用不到50行shell搞定了原来用300行C还没搞定的东西。

现在的版本是 0.2.1(0.2实现的依云需要的功能,结果忘了改下面的代码,于是又有了0.2.1),功能如下:

  • 智能判断分页器(more或你自己定义的,需要设置 PAGER 环境变量)
  • 无垃圾文件
  • 浏览 FreeBSD 的手册页

用法很简单

bsdman [要man的东西] [节]

代码很短,要看就自己看吧。。

仓库

*这是我在arch下第一个写的无意义的东西。

GIO 读写文件示例

#include <gio/gio.h>
#include <glib.h>

int
main (int   argc,
      char *argv[])
{
    /* 少写了这个程序就崩溃了 调试了老半天 T_T */
    g_type_init ();
    
    GFile            *file;/* 文件抽象数据类型 */
    GOutputStream    *fos; /* 用来写的 */
    GError           *error = NULL;
    
    /* 创建file对象 */
    file = g_file_new_for_path ("./test_file");
    
    /* 获取输出流 */
    fos = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, 
                                           G_FILE_CREATE_NONE,
                                           NULL, &error));
    if (!fos)
    {
        g_error ("%s", error->message);
        g_error_free (error);
        return 1;
    }
    
    /* 写入 */
    GString *str = g_string_new ("这些文字将写入 test_file。\n");
    g_output_stream_write_all (fos, str->str, str->len, NULL, NULL, NULL);
    g_output_stream_flush (fos, NULL, NULL);
    g_string_free (str, TRUE);
    
    /* 清理 */
    g_output_stream_close (fos, NULL, NULL);
    g_object_unref (file);
    return 0;
}
#include <gio/gio.h>
#include <glib.h>

int
main (int   argc,
      char *argv[])
{
    if (argc < 2)
        return 1;
    
    /* 少写了这个程序就崩溃了 调试了老半天 T_T */
    g_type_init ();
    
    GFile            *file;/* 文件抽象数据类型 */
    GInputStream     *fis; /* 用来读的 */
    GError           *error = NULL;
    GDataInputStream *dis; /* 抽象输入流 */
    /* 创建file对象 */
    file = g_file_new_for_path (argv[1]);
    
    /* 获取输入流 */
    fis = G_INPUT_STREAM (g_file_read (file, NULL, &error));
    if (!fis)
    {
        g_error ("%s", error->message);
        g_error_free (error);
        return 1;
    }
    
    /* 读取 */
    dis = g_data_input_stream_new (fis);
    char *line;
    while (TRUE)
    {
        line = g_data_input_stream_read_line (dis, NULL, NULL, &error);
        if (error)
        {
            g_error ("%s", error->message);
            return 1;
        }
        if (!line)
            break;
        
        g_print ("%s\n", line);
        g_free (line);
    }
    
    /* 清理 */
    g_input_stream_close (fis, NULL, NULL);
    g_object_unref (file);
    return 0;
}

效果

$ c89 -o reader reader.c `pkg-config --cflags --libs gio-2.0 glib-2.0`
$ c89 -o writer writer.c `pkg-config --cflags --libs gio-2.0 glib-2.0`
$ ./writer
$ ./reader test_file
这些文字将写入 test_file。
$ 

 

GNOME 密钥环密码简单存储API用法详解

该文基于我早前写 GKiu 时对 GNOME 密钥环的学习。

代码全部经过实测、优化,请放心阅读本文!

GNOME-Keyring 之前已经被 libsecret 取代了,以下内容仅作参考。

GNOME 密钥环是什么?

简单来说,就是存你密码的地方。假如吧,你在好多地方都办理了VIP卡,你总不能天天带在身上吧?而且还很麻烦,于是你就又买了一个保险柜,把你所有的VIP卡、钥匙、银行卡信用卡充值卡……都塞到这个保险柜里面了,你只需要一个密码就能打开找到自己需要的卡片钥匙。GNOME密钥环就是这么做的,它用一个密码锁住所有密码,于是你就不需要记住很多密码,只需要记住一个密码就全部可以了。需要放在正文里面强调的是强调的是,你用很多种不一样的密码正是因为安全原因,现在你正巧用了一个密码,所以骇客只需要获取你这一个密码你可就全线崩溃了,所以必须做好安全工作。当然,这是在本地存储的,所以要截获密码并不是那么容易。

GNOME 密钥环的一些问答

Q:我的系统有 GNOME 密钥环吗?

A:一般来说,只要你的桌面环境是 GNOME 就有。当然如果你有 KDE,安装了一些使用了这个库的软件,也会有。

 

Q:我需要手动使用它吗?

A:完全不需要,这个东西是给程序用的,所以都会自动(在你的选项下,也许sad)完成。

 

Q:如何调教密钥环?

A:呃。。。好吧,你可以用心灵感应遥控它,工具是强大到逆天的 seahorse,GNOME官方出品,质量有保证;还有出厂时候附赠的小刀一把,直拿软肋,名字就叫 gnome-keyring,不过因为是小刀有些人不会用(警察也不会让你用的),所以不太受欢迎。

如何在自己的程序里面使用 GNOME 密钥环?

这就是我们要谈论的重点了!因为是首次接触 GNOME 密钥环(也许你是sad),就算你以前用过 seahorse 也不一定用它的接口写过软件,所以就不会多做介绍给高级特性了!而且这部分也够绝大多数人用了,也许以后我还会多讲一些 GNOME 密钥环的 API。

如何安装开发包?

因为我是 Fedora 对 Ubuntu/Debian 系的不太了解,于是只给出了 Fedora 的安装方法,Ubuntu/Debian 自己解决吧。

方法:

sudo yum install gnome-keyring-devel

在接下来的实例环节,我们要多次用到 seahorse 来验证我们的代码运行结果,所以也许你还需要安装一下 seahorse。

sudo yum install seahorse

如何编译?

注意 GNOME 密钥环的开发文件偏离了一般实践,它将包命名为 gnome-keyring-1(而不是1.0),因此你需要这样编译:

cc [文件名] `pkg-config --cflags --libs gnome-keyring-1 glib-2.0`

因为 GNOME 密钥环用到了 GLib,因此你也需要链接它。

保存一个密码

现在就要开始学习使用GNOME密钥环库了!首先我们看看如何保存一个密码……

哇噢!这么长的参数列表!别着急,我们一个一个看,首先是这个 schema 参数。。。也许是的,GNOME 很多库都要这些东西,见怪不怪啦!长话短说,shema 就是一个定义,它定义了你这一个密钥环项目都保存了什么。那么。。莫非我们还要自己写一个 schema?!不瞒你说,GNOME库里面很多用schema的都非常复杂的定义!GNOME 密钥环也不例外,因此内部已经定义好了一个 schema,包含如下参数:

  • user:用户名。
  • server:服务器地址或名字。
  • procotol:用户用来连接到服务器的协议。
  • domain:域。
  • port:端口。

很显然这是一个用在网络上的 schema,而且令人一点也不意外的是,它这个名字就叫 GNOME_KEYRING_NETWORK_PASSWORD。

好了,我们已经干掉了前进路上的一个很大的障碍!继续前进!

keyring,这个很简单了,就是说要存到哪个密钥环里面嘛!不过问题是,这个类型怎么是 const gchar *?呃,其实每个密钥环是用名字标示的,比如你买了好几个一样的保险柜,要区分哪个是不是要贴上一张标签?那我们如何知道系统已有哪些密钥环呢?还要自己创建?还是枚举出一个最合适的已有的?不需要了!默认GNOME密钥环已经有了一个默认的,我们只需要在这里填上一个 NULL 就OK了,为了让代码更加可读(也更长),于是他们又定义了一个为NULL的GNOME_KEYRING_DEFAULT宏!

接下来的已经没什么比较需要讲解了,因为从名字就能看出来是什么意思。如果你细心的话。。你可能已经发现了一个后面带有 _sync 的同名函数,这是干什么的?嗯,其实默认情况下是异步运行的,也就是这个函数会立即返回并创建一个以回调函数为线程函数的线程,于是你就无须等待,这在一些需要大量存取的情况下非常有效,但是,我们一般的小程序只需要存一两次,为什么需要异步?那就用同步函数好了!也就是说,当操作完成后才会返回(当然,为了内容完备,我们把两个都讲解一下)。

但是你可能会疑惑,这个 destroy_data 又是做什么的呢?这就是另外一个需要的函数了,如果你传递了一个非 NULL 的 data(也就是GTK+里面的用户数据),那么函数会调用你指定的这个函数来释放你这个 data 的内存。

现在有了丰富的理论基础,我们先写一个异步版本的密钥环保存实例!

(在我这里似乎没有进入回调函数,这也可能成为我们使用同步版本的一个理由)

#include <stdlib.h>
#include <stdio.h>
#include <gnome-keyring.h>

static void save_cb (GnomeKeyringResult result,
                     gpointer data)
{
    if (result != GNOME_KEYRING_RESULT_OK)
    {
        fprintf (stderr, "保存密码出错:%s!\n",
                 gnome_keyring_result_to_message (result));
    }
    else
    {
        printf ("保存密码成功!\n");
    }
}

static void free_data_save_cb (gpointer data)
{
    free (data);
}

void 
save_password (const char *usr,
               const char *pwd)
{
    gpointer data = malloc (sizeof (100));
    gnome_keyring_store_password (GNOME_KEYRING_NETWORK_PASSWORD,
                                  GNOME_KEYRING_DEFAULT,
                                  usr, /* display name */ 
                                  pwd, /* password */
                                  save_cb, 
                                  data, free_data_save_cb,
                                  "user", usr,
                                  "server", "http://ekd123.org",
                                  NULL);
}

int main ()
{
    save_password ("mike", "123456");
    sleep (10); /* 必须sleep,否则程序退出就无法看到效果了 */
    return 0;
}

在回调函数里,如果出现错误会使用 gnome_keyring_result_to_message 将结果转化为字符串的消息(如 strerror 所做一样)。

有必要强调一下,在 destroy_data 参数后面就是 schema 提供的参数了,你必须是一键一值,最后用 NULL 结尾,但我不明白的是,为什么需要这个,因为搜索查找的都是使用 display_name (也就是在 seahorse 中展示的名字)。确实是 seahorse 显示的名字,但是查找还需要这些 schema 中的参数。

可以看到,这个异步版本的非常复杂,而且要返回结果也是迂回的,所以一般实践还是喜欢用同步版本。因此在这里再给出一份存储密码的同步版本。

#include <stdio.h>
#include <gnome-keyring.h>

void 
save_password (const char *usr,
               const char *pwd)
{
    GnomeKeyringResult r;
    r=gnome_keyring_store_password_sync (GNOME_KEYRING_NETWORK_PASSWORD,
                                         GNOME_KEYRING_DEFAULT,
                                         usr, /* display name */ 
                                         pwd, /* password */
                                         "user", usr,
                                         "server", "http://ekd123.org",
                                         NULL);
    if (r != GNOME_KEYRING_RESULT_OK)
    {
        fprintf (stderr, "不能存储密码:%s!\n", 
                 gnome_keyring_result_to_message (r));
    }
    else 
    {
        printf ("存储密码成功!\n");
    }
}

int main ()
{
    save_password ("mike", "123456");
    return 0;
}

很明显地,这个版本的代码缩减了许多,而且更易理解,当我按下回车键后,屏幕上显示出了我意料之中的喜讯。

关于运行效率,time可以告诉我们更多:

$ time ./a.out
存储密码成功!
./a.out  0.01s user 0.02s system 3% cpu 0.878 total

对于普通人来说,这点时间根本没有注意到就溜走了,所以并不成什么问题!

如果你真的要刨根问底,一睹真实效果的话,我只能有图有真相地给你答复:

(背景图为未来 Fedora 16 的背景图,个人非常喜欢)

“切,那不过是你用seahorse伪造的而已。”呃,你这么想就大错特错了,因为我还会使用 find_password 来找回这个密码!

寻找一个密码

还是按照惯例,先上异步版本,再上同步版本,为了代码简洁,我会忽略掉用户数据参数。因为 gnome_keyring_find_password 比存储密码的函数简单多了,所以就不会再解释参数意思了。

#include <stdio.h>
#include <gnome-keyring.h>

static void find_cb (GnomeKeyringResult result,
                     const char *string,
                     gpointer data)
{
    if (result == GNOME_KEYRING_RESULT_OK)
    {
        printf ("找到了密码!密码是:%s\n", string);
    }
    else
    {
        fprintf (stderr, "查找密码失败:%s。\n",
                 gnome_keyring_result_to_message (result));
    }
}

void find (const char *usr)
{
    gnome_keyring_find_password (GNOME_KEYRING_NETWORK_PASSWORD,
                                 find_cb,
                                 NULL, NULL,
                                 "user", usr,
                                 "server", "http://ekd123.org",
                                 NULL);
}

int main ()
{
    find ("mike");
    sleep (1);
    return 0;
}

注意回调函数的第二个参数,是带有 const!这意味着你不能任意地 free 它。

看上去还是异常复杂,反对 store_password 的理由同样适用于这里,何不试试同步版本?不论从哪方面来说,同步版本都比异步版本易用(好吧,其实在任何方面,异步都比同步复杂;线程中的同步与这里的意思不同,而且它非常复杂)。

#include <stdio.h>
#include <gnome-keyring.h>

void find (const char *usr)
{
    gchar *pwd;
    GnomeKeyringResult r;
    
    r=gnome_keyring_find_password_sync (GNOME_KEYRING_NETWORK_PASSWORD,
                                        &pwd,
                                        "user", usr,
                                        "server", "http://ekd123.org",
                                        NULL);
    if (r == GNOME_KEYRING_RESULT_OK)
    {
        printf ("找到了密码!密码是:%s\n", pwd);
        gnome_keyring_free_password (pwd);
    }
    else
    {
        fprintf (stderr, "没有找到密码。。%s\n", 
                 gnome_keyring_result_to_message (r));
    }
}

int main ()
{
    find ("mike");
    return 0;
}

欢快的喜讯传来了,找到了密码!!哈哈,前面那个反派呢?现在信了吧!不管你信不信,反正我信了!

删除密码

如果你要删除一个密码,也是非常容易的,因为删除API是最简单的API!

看了例子就知道了!按惯例,异步在前。

#include <stdio.h>
#include <gnome-keyring.h>

static void del_cb (GnomeKeyringResult result,
                    gpointer data)
{
    if (result == GNOME_KEYRING_RESULT_OK)
    {
        printf ("成功删除了密码!");
    }
    else
    {
        fprintf (stderr, "删除密码失败:%s!\n", 
                 gnome_keyring_result_to_message (result));
    }    
}

void del (const char *usr)
{
    gnome_keyring_delete_password (GNOME_KEYRING_NETWORK_PASSWORD,
                                   del_cb,
                                   NULL, NULL,
                                   "user", usr,
                                   "server", "http://ekd123.org",
                                   NULL);
}

int main ()
{
    del ("mike");
    sleep (1);
    return 0;
}

是比存储密码简单了许多!但是,对比了下面同步版本,就略显复杂了:

#include <stdio.h>
#include <gnome-keyring.h>

void del (const char *usr)
{
    GnomeKeyringResult r;
    
    r=gnome_keyring_delete_password_sync (GNOME_KEYRING_NETWORK_PASSWORD,
                                          "user", usr,
                                          "server", "http://ekd123.org",
                                          NULL);
    if (r == GNOME_KEYRING_RESULT_OK)
    {
        printf ("成功删除了密码!\n");
    }
    else
    {
        fprintf (stderr, "删除密码失败:%s\n", 
                 gnome_keyring_result_to_message (r));
    }
}

int main ()
{
    del ("mike");
    return 0;
}

看,这个才算简单的!有图有真相:

在此我还是向大家力荐使用同步版本,一般情况下同步版本带来的好处远大于弊端(除非你有特殊的环境),而且带来的延迟微不足道,调试起来也更加方便(会在完成后才返回)!

其它问题

你可能觉得奇怪,为什么不用输入密码都能查找出来?那岂不是非常不安全?嗯,这个你大可放心,因为这是用你登录密码加密的,所以根本不用担心。但是如果你自己创建一个密钥环,那可就得需要密码啦!当然你可以让用户输入,也可以自己选定,一切由你决策!wink

更新到 Fedora Rawhide

一。Fedora Rawhide 是什么?

简单的说,Rawhide就是Fedora的滚动更新版,但这与 Gentoo、ArchLinux 等又不同,因为这个分支指向的是当前开发版(如同 FreeBSD 的 CURRENT 分支),所以极其不稳定。在更新前用你的脑子想想干什么?

需要注意的是,这不是测试版,是开发版,比如现在是 Fedora 15,进行中的版本是 Fedora 16,而 Rawhide 已经指向 Fedora 17 了。

某人说这是“最激进发行版的最激进分支”,窃以为非常贴切。

二。为什么需要 Fedora Rawhide?

为 Fedora 开发者提供一个快速的反馈平台,所以一般都是开发者在用,普通用户一般用不到,当然如果你有开发经验而且有一定的解决问题能力可以尝试。

三。如何安装 Fedora Rawhide?

这是非常简单的,只需要

sudo yum install fedora-release-rawhide
sudo yum update --disablerepo=\* --enablerepo=rawhide

即可。我强烈建议不要任何在X下的终端模拟器!因为我在使用的时候不知怎么 X 突然崩溃了,yum当然也崩溃掉了,因为它是一个模拟出来的终端。这样我就引来了好多麻烦的问题。更新途中突然崩溃的结果就是这个,要是恰巧包管理也坏掉了,那就囧了,所以一定要小心

更新的时间会非常长,因为要更新电脑上所有的软件包,即使版本号一样,包名也不一样,比如 xxx.fc15 一定要更新到 xxx.fc17(没有17的话也一定会有16的)。建议你在睡前进行更新并关掉电源选项中的X分钟后睡眠、挂起,这会断网的。

在更新途中你可能会遇到各种各样的问题如“损坏依赖”“冲突”“未找到”等等,非常麻烦,一定要做好心理准备,当然一旦开始就没有什么问题了,除非突然给你说 404 错误。

四。这个 Rawhide 源好慢啊!

那是因为 Rawhide 源默认指向一个列表,而如果你没有安装选择最快的源的插件,一般都非常慢,这里我们可以选用 163、网易等国内源来加速。不过这需要自己修改源。

打开 /etc/yum.repos.d/fedora-rawhide.repo,将所有baseurl前的#去掉,再改为你用的源的URL。附上一份我的fedora-rawhide.repo(163的,特点是更新快,不过速度比搜狐慢点,搜狐更新很慢)。

[rawhide]
name=Fedora Rawhide - $basearch - 163.com
failovermethod=priority
baseurl=http://mirrors.163.com/fedora/development/rawhide/$basearch/os/
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=fedora-rawhide&arch=$basearch
enabled=1
metadata_expire=7d
gpgcheck=0

[rawhide-debuginfo]
name=Fedora Rawhide - $basearch - Debug - 163.com
failovermethod=priority
baseurl=http://mirrors.163.com/fedora/development/$basearch/debug/
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=fedora-debug-rawhide&arch=$basearch
enabled=0
metadata_expire=7d

[rawhide-source]
name=Fedora Rawhide - Source - 163.com
failovermethod=priority
baseurl=http://mirrors.163.com/fedora/development/rawhide/source/SRPMS/
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=fedora-source-$releasever&arch=$basearch
enabled=0
metadata_expire=7d

注,该repo是我空写出来的,所以有一点小问题,建议你自己修改安装fedora-release-rawhide后出现的repo文件。

五。我不想用 Rawhide,可不可以用下一个版本?

当然可以,而且比安装 Rawhide 更加方便,你只需要安装 preupgrade 即可,这是一个图形软件,很方便,唯一需要注意的是,你的 /boot 分区至少需要 500M 空余空间。

六。可能遇到的问题

我这里遇到了一个很郁闷的问题,就是开机没法显示图形界面,这个问题很容易知道,显然是显卡问题。

这个问题也不是很难解决,只要用一个禁用调试的内核就解决了,你可以去bodhi和koji上搜索查找(描述里面会说 disable debug build),从Koji上下载下来,安装即可解决问题。注意千万不要升级内核,除非你找到了新的禁用调试的内核。

 

(Windows)预编译的 GTK+ 3.0 DLL 和开发包

Mike's Gtk3 All-In-One Bundle。

详见其中的README文件。

大概是开发文件、运行时和别的东西。

下载地址——Skydrive

文件名:mike-gtk3-bundle.7z。

继续阅读

汇编条件判断整理(JCC,CMP/TEST的实现)

没错,就是整理,因为我其实什么都不知道。大多数来自互联网,网址丢了,对原作者说声对不起。不过也补充了自己一些内容。

这篇文章算是对我以前的一套汇编教程if分支节的补遗和扩展阅读。

其实汇编挺重要的,比如这篇文章所述,我也答成B了。。。

比较的实现

我们知道CMP是比较两个寄存器内容的指令,但这是如何实现的?

当执行到CMP指令的时候会读取这两个寄存器的内容,并加以减法运算,结果本身不保留,并按照结果设置符号位(属算术运算)。

CMP是一个经常使用的指令,大多用来测试数字的大小。一个常见的例子

MOV EAX, 10
MOV EAX, 10
CMP EAX, EBX   ;相减求出结果,为0,将1存入ZF
JE  SOME_WHERE ;检查ZF,为1就跳
JNE SOME_WHERE ;检查ZF,为0就跳

当执行到TEST指令的时候会读取这两个寄存器的内容,并加以按位与运算,结果不保留,并按照结果设置符号位(属逻辑运算)。

TEST是一个用来检测内容而不是运算内容的,经常用的一招是测试寄存器是否为0:

TEST EAX, EAX
JZ   SOME_WHERE

某个参考资料说 TEST EAX,EBXAND EAX,EBX 是一样的,窃以为不同,因为汇编的所有算术指令都是破坏性的,它会把结果存入 EAX,而TEST不会(就像C代码 a &= b;)。若要 AND 也不会破坏原值,只能先入栈存值,然后在出栈前转移结果,就像如下所示:

MOV  EAX, ??  ;赋值
MOV  EBX, ??
PUSH EAX      ;入栈保存EAX
AND  EAX, EBX ;运算
MOV  EDX, EAX ;保存结果
POP  EAX      ;弹出恢复EAX

但是你要自己做一个CMP指令是不切实际的,因为你自己还是要判断符号位的值,最终还是用到了TEST, CMP这些指令。

符号位表

这些符号位存在一个叫做PSW(Program Status Word,程序状态字)的16位(4字节)寄存器里面。

符号位 叙述 典型应用
OF 溢出标志,标明一个溢出的运算。真置1,假置0。 这个溢出,非溢出,我想我还没有弄懂
SF 负号标志,标明结果为负数。真置1,假置0。

int i = -100;

if(i < 0)

goto somewhere;

ZF 零标志,标明结果为0。真置1,假置0。 见上cmp例子
CF 进位标志,标明结果进位了。真置1,假置0。

MOV EAX,1

MOV EBX,9

ADD EAX,EBX

AF 辅助进位标志,记录运算时第3位(半个字节)产生的进位。 <null>
PF 奇偶标志,结果操作数中1的个数为偶置1(我猜是二进制下)。 <null>
DF 方向标志,在串处理指令中控制信息的方向(非运算) (null)
IF 中断标志(非运算) (null)
TF 陷井标志(非运算) (null)

其中前几个称为运算条件码(condition code),后三个是逻辑控制标志位,我们在此对它们不感兴趣。

JCC指令表

JCC指条件跳转指令,CC就是指条件码。

JCC指令 中文含义 英文原意 检查符号位 典型C应用
JZ/JE

若为0则跳转;

若相等则跳转

jump if zero;

jump if equal

ZF=1

if (i == j);

if (i == 0);

JNZ/JNE

若不为0则跳转;

若不相等则跳转

jump if not zero;

jump if not equal

ZF=0

if (i != j);

if (i != 0);

JS 若为负则跳转 jump if sign SF=1 if (i < 0);
JNS 若为正则跳转 jump if not sign SF=0 if (i > 0);
JP/JPE 若1出现次数为偶数则跳转 jump if Parity (Even) PF=1 (null)
JNP/JPO 若1出现次数为奇数则跳转 jump if not parity (odd) PF=0 (null)
JO 若溢出则跳转 jump if overflow OF=1 (null)
JNO 若无溢出则跳转 jump if not overflow OF=0 (null)
JC/JB/JNAE

若进位则跳转;

若低于则跳转;

若不高于等于则跳转

jump if carry;

jump if below;

jump if not above equal

CF=1 if (i < j);
JNC/JNB/JAE

若无进位则跳转;

若不低于则跳转;

若高于等于则跳转;

jump if not carry;

jump if not below;

jump if above equal

CF=0 if (i >= j);
JBE/JNA

若低于等于则跳转;

若不高于则跳转

jump if below equal;

jump if not above

ZF=1或CF=1 if (i <= j);
JNBE/JA

若不低于等于则跳转;

若高于则跳转

jump if not below equal

jump if abow

ZF=0或CF=0 if (i > j);
JL/JNGE

若小于则跳转;

若不大于等于则跳转

jump if less

jump if not greater equal

SF != OF if (si < sj);
JNL/JGE

若不小于则跳转;

若大于等于则跳转;

jump if not less;

jump if greater equal

SF = OF if (si >= sj);
JLE/JNG

若小于等于则跳转;

若不大于则跳转

jump if less equal;

jump if not greater

ZF != OF 或 ZF=1 if (si <= sj);
JNLE/JG

若不小于等于则跳转;

若大于则跳转

jump if not less equal

jump if greater

SF=0F 且 ZF=0 if(si>sj)

这里有好多相等的指令(啊哈,这里有一个有意思的现象,好多看似不沾边的东西实际上是相等的!),我猜是因为编译器编译起来就更方便了,不过做一个表也没什么难的,这个结论不成立啊……

这里有一点要指出,无符号数用低于、高于来比较,而有符号数用大于、小于比较。

让 JED 看起来更像窗口程序

本文大量依赖 gnome-terminal,如果你用 XtermKonsole,现在就可以离开了。

不过知道方法也可以:用你当前的图形终端模拟器给 JED 加一个外壳。我们这里起的名字叫 gjed,如果你用 Konsole 可以叫 kjed啥的,其实 JED 自身有窗口版本,叫做 XJed,不过 Fedora 没有。

关于 JED 是什么,我就不赘述了,在上一篇《扔掉 Emacs,投奔 JED》中已经介绍过了。当然如果你天天开终端,然后输入 jed 也没什么不好,不过多了就觉得,能直接双击打开文件多好啊!

主要问题是,Fedora没有 xjed!所以只好自己 DIY 了。

我们还是使用上次在《只让Emacs以守护进程模式运行》中的方法,做一个脚本!呃,早在那个文章里我不就说了我经常用这种方法投天换日、瞒天过海、偷梁换柱……

这里我们首先要了解一下 gnome-terminal 的参数,我们要用到的是 -x,-t,--hide-menubar。

  • --hide-menubar 隐藏菜单,才能按F10,不过 ESC m 也可以。
  • -x/-e          运行命令,在该参数后都被解释为命令,所以必须是最后一个参数。
  • -t             修改标题。

所以我们可以写这个叫做 gjed 的脚本放在/usr/bin下:

#!/bin/sh
gnome-terminal -t 'JED in GTK+' --hide-menubar -x jed $*

然后你就可以在运行对话框中输入 gjed 回车,就能看到了。

我们现在可以在 Gnome Shell 中或 Gnome Panel 中建立一个启动器,复制到 /usr/share/applicantions。

建立的方法是使用终端,输入

gnome-desktop-item-edit GJED.desktop

接着在命令里面输入 gjed,名称 GJED,图标可以任选。然后修改它,加一行,写上

Categories=GTK;Utility;TextEditor;

Gnome 3 看:

点击活动,在应用程序中找到 GJED(可能需要反复等待缓存刷新),拖到旁边的 dock。

Gnome 2 看:

拖动到上面的面板上。

 

完毕

扔掉 Emacs,投奔 JED

我原来的 Emacs 文件现在已经扔在了 115 网盘。点这里下载。

JED 是一个更小更快的 Emacs 实现。它用 S-Lang 作为扩展语言而不是 Emacs Lisp。S-Lang 是一个类 C 的脚本语言,作为扩展语言真是太合适不过了。

在 Fedora 上可以用 sudo yum install jed 来安装 JED(不过貌似没有用于 X 的 XJED)。安装后在终端上输入 jed 就能启动了。

默认安装下,jed的速度相当快,完全比过了 vim(另一个强大的编辑器)。

如果你要扩展你的 jed,可以去 JED Modes Repository,这里有很多让你的 JED 更加强大的 Mode。

要使用这些 Mode,在你的 ~/.jedrc 中写上 require ("mode名字"); 即可。

另外特别附上我现在用的 .jedrc。

%% 
%% dot jedrc of Mike Manilone
%% 



% 快速切换buffer
require("numbuf");

% 行号
LINENUMBERS=2;
public define global_mode_hook (hook_name)
{
    toggle_line_number_mode ();
}

% C缩进格式
c_set_style("bsd");
TAB_DEFAULT=4;
USE_TABS=0;

% 配色
set_color_scheme ("black3");

% 无~备份
No_Backups = 1;

熟悉C语言的你,是不是感到特别亲切呢?

这里唯一需要你动手的是在这里下载 numbuf 并放到 /usr/share/jed/lib/ 下,然后就可以用了。很可惜我经常用的tabbar和Alt + 左右键切换buffer没有,不过 S-Lang 很简单,不知道哪个大牛给写一个~

更新:

jed没有标签窗口,所以tabbar不可能实现,不过有一种变相实现的方法,Buffers->Change Buffer底下不就是Buffer列表吗?我们可以绑定它啊!所以:

setkey("menu_select_menu(\"Global.&Buffers.&Change Buffer\")", "\ez"); % alt+z显示buffer切换菜单

感谢 John E. Davis 提供的技巧(原文见此,很有价值)。

我们还能绑定ctrl+alt+n到下一个buffer(可惜的是没有向前)

setkey ("next_buffer", "\e^N"); 

Is-Programmer博客小技巧汇总

从BUG反馈中整理。

这些小技巧大多数是和自定义CSS有关的,你可以去后台->插件(Plugins)->自定义CSS(Custom CSS)中操作。

因为我个人对CSS不甚了解,所以希望 galeki 或者 CSS 大牛对以下内容进行审校,非常感谢~

带链接的图片有下划线,要去掉

原因:这个是皮肤的默认链接样式造成的。

方法:自定义CSS

a.lightbox{border:0;}

主体文本颜色混乱

原因:因人而异。

方法:自定义CSS

body{color:#000;}

将其中的color改成喜欢的即可。

代码高亮框会少一点点高度盖住最后一行的下划线

也许已经修复了,不过我是用了这个代码的,也不知道~smiley

原因:???

方法:自定义CSS

div.syntaxhighlighter{overflow-y:hidden !important;}

修改背景图

没有原因。

方法:自定义CSS

body{
background-image: url("你的图片网址");
}

代码高亮框的横向滚动条

已经fix了,不过还是记录一下。

方法:自定义CSS

div.syntaxhighlighter
{width:500px !important;overflow-x:scroll !important;}

500px按自己喜好修改。

嵌套回复有点大

貌似fix了,我没有在意这种事情。(啊!galeki……)

现在可能已经可以动态调整了,当然你还是不喜欢可以自己调整。

方法:自定义CSS

.reply_comment_box{margin-left:3px !important;}

把3px修改成自己喜欢的。

每个分类的RSS

原因:就是想要细化一下RSS而已嘛。。。(个人觉得把留言、评论和文章都做成RSS有点不必要。)

方法:点击某个分类的链接,在浏览器的地址栏的后面加上“.rss”,回车,就是这个分类的RSS Feed了。

主题在宽屏上太窄了

原因你懂的。。

方法:自定义CSS

#container, #menuh-container{width: 1000px;}

1000改成喜欢的。

不过这样,窄屏看起来就麻烦了,不推荐。

自定义顶部图片

自定义CSS

#top{
background-image: url("图片网址");
}

导航栏乱七八糟

进入 后台->外观->导航栏 设置。

首页文章标题设置颜色

还是自定义CSS

h2.title a { color:#xxxxxx !important; }

把xxxxx改成你想要的颜色值。

设置“引用”样式

点击这里学习更多

更多技巧整理中……

如果大家想要归类的话,留言一下,我比较懒,呼声高就归类一下。