x64 参数传递

近日某青年似乎研究到x64(AMD64 in history)的参数传递调用约定,这玩意确实和x86上面不一样,于是我决定写点字介绍一下。

x64首先把x86原有的寄存器扩展到了64位,然后更增加了8个通用寄存器:R8~~R15,嗯,确实有点RISC的味道。

  • x64上面默认的函数调用约定是fast call,也就是ABI是fast call。
  • 前四个参数传递顺序是RCX,RDX,R8,R9,其余的参数通过压栈传递。注意这里有一个细节:前四个参数也是占用栈空间的,或者说,栈需要为前四个参数保留32个字节。
  • 小于64位的参数传递时高位并不填充零,大于64位需要按照地址传递。
  • 返回值在RAX
  • 被调用函数不负责清栈
  • RAX,RCX,RDX,R8,R9,R10,R11是“易挥发”的,其余寄存器需要保护。
  • 栈需要16字节对齐。

OK,以上是理论上的东西,实际上编译器会把一切都搞糟,具体可以看一下两篇文章:

The history of calling conventions, part 5: amd64

Although the x64 calling convention reserves spill space for parameters, you don’t have to use them as such

这一切看起来非常的令人迷惑,个人推荐的解决办法有三种:

  • 使用ICC或者GCC,这样可以用内联汇编,于是绝大多数问题都解决了。
  • 使用编译器 intrinsics 指令,这玩意好像应该翻译成内省指令,还是内醒,总之不管了,知道是这玩意就行。
  • 手工代码发射,不过这个最好还是用在API hook的时候,写算法真还不如用MASM,不过MASM免不了还得和参数调用约定捉迷藏。

全脑瘫IT时代(六)

这个系列我很久没更新了,因为脑瘫的软件和硬件确实不那么常见。不过,今天我又遇到了一个完美的素材。

Altova UModel

Altova UModel 应该是除了ROSE之外少数硕果仅存的UML工具之一,功能也确实没的说,很好,很强大。但是这软件的代码逆向功能却有一个真正全脑瘫的设计:

image

当我们选择从代码逆向生成顺序图的时候,遇到空的方法就会有这个提示。也许各位看官觉得,嚯,这算神马问题啊,多user friendly的提示啊。

当你正在逆向一个15w行代码的工程的时候,需要6个小时,可能会有600多次这样的警告的时候,一切就不那么好玩了。因为这个窗口是模态的,不点掉分析就会停止。于是,我们不得不傻逼兮兮的看着屏幕,盯着Altova UModel,如果没有及时点掉这个警告,那计算机可就怠工了。我试图找到关闭这种提示的选项,但是我没有成功。

另外每生成一张顺序图,Altova UModel都会即时刷新绘图区……嗯……这个有多么脑瘫不多说了,各位看官想象一下6000张顺序图打开6000个窗口的壮观景象吧。

一个号称工业级的UML工具,是不是只能用来分析不超过1w行代码的工程呢?

让 UV4 支持STC 单片机

Keil 本身并没有自带 STC 8051 单片机的数据,这样用起来就非常令人不爽,好在国内有个青年已经整理了一个补丁

这个补丁包含三个修正:

  • 汉字bug修正,这个是老生常谈了,很奇怪Keil十年来都没有修正这个,说明其对中国市场完全漠视的态度。
  • STC头文件
  • STC器件数据库

OK,就一般应用来说这个补丁已经足够了,但是对于追求完美的人来说还略有不足,因为这个补丁会覆盖掉UV4自带的器件数据库UV4.cdb。打上补丁就丢失了最新的UV4数据库。

怎么解决这个问题呢,其实自UV2以来,就支持用户自定义器件数据库的功能,我们可以按照以下方法来修改:

  • 备份UV4.cdb
  • 安装补丁
  • 修改 C:\Keil\TOOLS.INI,在[UV2]一节下面增加

    CDB0=uv4\custom.cdb("STC 8051")

  • 将补丁安装的UV4.cdb改名为custom.cdb
  • 将备份的UV4.cdb恢复

这样下次我们选择器件数据库的时候,UV4就会问我们要从哪个库里面选取了。

    沃尔玛的问题

    沃尔玛在渝2年屡出食品问题 售过期板鸭遭罚款34万

     

    看到这个新闻我一点都不惊讶,2009年我曾在知春路沃尔玛买到过长绿毛的馒头,粗粮加上包装买的时候没看出来,回到家只能算一个哑巴亏了。在那以后我就没去过沃尔玛,这种黑心企业必须要抵制。

    Live Space的谢幕

    05年的时候,我开始在Live Space上写博客。昨天,Live Space正式关闭,我不禁感到一丝惆怅……

    当时在Live Space上开辟空间,最初的打算就是靠着大树好乘凉,微软应该不是朝三暮四、轻易倒掉的厂商。我本以为自己不会在那个博客网站昙花一现的时代为迁移博客而大费脑筋,结果谁也无法预知未来。

    如今,我已经迁移到了WordPress和网易,希望这次能安稳的久一点。

    为什么没有“128位”的通用处理器

    在专用领域,比如DSP,GPU中,通用寄存器通常都很宽,也就是说大于通常的32位或者64位。其原因在于,这些针对特定领域设计的处理器,其硬件架构是为问题服务的,举例来说,GPU处理颜色的时候,一个像素ARGB是四个32位或者16位的浮点数,所以寄存器有128位或者64位宽也就不足为奇了。

    那么我们为什么没有见到,或者说市场上为什么没有“128位”的通用处理器呢?这有很多计算机体系结构的原因在里面,容我一一说来:

    首先,我们得定义这个“128位”是什么。以传统的POWER、x86和x64来说,处理器的位数是用通用寄存器的宽度来定义的,即32位处理器的通用寄存器是32位,64位处理器的寄存器是64位,那么如果我们有了128位处理器,也应该一样。但是,这么做有必要么?常规的整数运算是用不到这么大的寄存器的,真正的大数运算也不会用这种方法来实现。而在现代的32位、64位处理器中,更重要的浮点运算所使用的浮点寄存器早已经是128位甚至256位了。所以128位通用寄存器在这里没什么意义。

    那么就有人说,我们需要128位的寻址能力。好吧,64位的寻址能力是2^64字节,大约是1.84467441 × 1019 字节,如果你对这个科学计数法表示的数字没什么感觉,我用另外一种写法:18.45 EB 也就是大约18200000 TB,如果说这个不够用,那你需要的不是人类目前的硅芯片计算机,你需要求助于E.T.。

    使用大地址空间有几个额外的问题,尤其是对RISC处理器来说,会带来致命的性能问题。很多用户,尤其是初级的计算机用户,并不知道RISC这四个字母下隐藏的计算机哲学,或者说艺术:所有的OP code都是定长。以POWER为例,访问32位的常量地址,需要分两次计算16位的地址,因为OP code中只有16bits来存放这样的数据,64位则需要四个OP存放。而在CISC处理器中,地址可以直接编码在指令里,导致指令明显变长,比如32位的跳转通常是5个字节,而64位下面甚至需要15个字节。这只是问题的开始:随着使用的OP的增多,对CPU总线和cache的压力也越来越大,原本一个时钟周期能fetch两条指令,现在可能一条都取不到;原本可以存放两条、四条指令的cache空间,现在只能存放一条指令。

    另一个原因是程序中的数据结构。学过计算机科学初级内容的人都知道,现代数据结构中最最最最最基本的要素是:指针。大多数关键的数据结构都离不开指针:链表、树……,对于程序来说,从32位编译成64位会大幅增加运行时的内存消耗,道理很简单,指针本身变长了,存储指针自身需要的空间增加了。变成128位是什么样呢?可想而知。同样访问内存中的数据需要更多的时间,因为数据本身变大了,假设一个结构体里面有两个指针,32位下编译出来需要8个字节,64位就需要16个字节(假设4字节对齐)。同理,cache面临更大的压力。

    上面是软件上的,或者说是理论上的,那么我们来看看硬件上的问题。既设我们需要制造“128位”的通用处理器,有128位的地址总线,128位甚至256位的数据总线,那么什么样的封装能满足要求呢?在现代处理器3~~4G的这个工作频率上,安排这么大量的总线连接,那么保守估计需要1500~~2500个针脚的封装才能稳定工作(需要大量的供电和接地针脚来瓶很电流和改善信号质量),而且这么高密度的,还有大电流,估计要12~~24层布线,设计生产这样的一块PCB本身就是挑战电子制造业,至于良品率和价格就不敢想了。

    既然我们有了便宜的4核、8核处理器,为什么要设计生产完全不可行,没有任何工业和商业价值的“128位”处理器呢?所以,市场上没有“128位”通用处理器。

    DX 贴膜秘籍

    UntitledE-INK的脆弱是总所周知的,加之DXG的屏幕又比较大,所以贴张膜方便以后清理还是很有必要的,现在最常见的是这样的膜,市价大约30元上下:

    但是,这个膜有一个很大的问题就是,它的尺寸太精确了,精确到什么程度呢?和屏幕尺寸的误差不超过1mm!而DXG的屏幕是凹进去的,换句话说,一旦贴上,再想揭开几乎没有任何稳妥的办法,我在论坛上看到有各种主意:绣花针挑,牙签,甚至还有拆机的……这样的操作显然已经违背了贴膜保护屏幕的初衷了。

    那么怎么解决呢?其实只要贴之前对贴膜做一个小手脚就可以了:

     

     

     

    cut找一个你认为不重要的角(我倾向于左下角),用剪刀剪去大约2mm宽的一条即可(见左图)。对于9.7寸这么大的膜来说,剪去这么一点完全没有影响。

     

     

     

     

     

     

    cut2

    以后想要揭开,或者干脆就是贴的时候没贴好想揭开处理,就很简单了,找一张比较薄又比较有韧性的纸,比如杂志用的铜版纸或者超市小条,裁下10x30mm的一条慢慢从这剪去的一角插进去(见左图),然后用透明胶带纸和膜本身固定即可,然后就随便揭开处理了。

    Kindle DXG

    An friend from USA bought a Kindle DXG for me, it really looks very nice

    20110128412

    2011012740420110127407

    Cheap HDD bracket

    I use a very old Computer Case at home, it has only 3 3.5 HDD slots, and hard to install.

    Some days ago, I bought a Seagate 7200.12 1TB HDD (mmmm…, Seagate again >.<), and a HDD bracket. The bracket costs 7$, sounds cheap, let’s look it:

    20110117391

    It comes with screws, for install 4 HDDs and fixate into case.

    20110117393

    OK, this is two HDDs fixated on it, looks very nice:

    20110129421

    Finally, in the case:

    20110129422

    Repair it yourself

    My office computer has a Seagate 7200.11 500G HDD. One day morning when I powered on the machine, I got this:

    51_23268_3bec7fbb0b893bf

    The HDD disappered in BIOS, so I got a Seagate brick… and I lost 500G data.

    If I send this brick to Seagate, I can sure I’ll lost my data forever, so I decide repair it myself.

    First, I bought a Nokia CA-42 Cable, cost about 0.7$, and jointing it with minimal plug head:

    51_23268_315551538797438

    Second, plug a thin plastic strip between the HDD motor and PCB:

    51_23268_56440a254a4d99d

    OK, all ready.

    Plug the CA-42 Cable in to an bootable computer and install cable driver, launch terminal, get into HDD factory mode, type commands to repair(reset) it. 10 minutes later, all data is back.

    Then, I update this HDD firmware from SD15 to SD1A, prevent it damage again.