程序设计ASM1 ASP1 C4 C#1 C++1 C语言1 LUA3 Node.js1 PHP11 SQL1 VB4 html2 批处理12 综合7 资料3

  • 非内置SCSI驱动在PE下的安装过程

    在PE下安装硬盘控制器驱动都是失败的,因为都是使用DEVCON类. 由我之前发的贴子[原创]让你的PE/XP/2003系统支持EXFAT. 我突然想到,SCSI驱动是不是也可以使用类似的方法呢,实验证明我的想法有一定的可行性(因无条件进行全面测试)

  • 批处理脚本整理之邮箱自动登录示范(亿邮首页eyou)

    有时想用批处理登录邮箱,如果这个邮箱登录支持GET方式的话只要构造一个URL地址提交就可以了,如果不支持上URL提交就不行了,这时可以参考以下代码 上面的HTA也可以改为HTM,如果你的电脑不支持HTA的话.原理很简单,从上面的代码就可以看到.当然了,这个方法并不一定是最好的.用VBS或其它的工具一样可以实现.

  • [整理] Windows Api 调用 keybd_event 相关资料(VB)

    keybd_event VB声明. VB声明 说明 这个函数模拟了键盘行动 参数类型及说明 bVkByte 欲模拟的虚拟键码 bScanByte 键的OEM扫描码 dwFlagsLong 零;或设为下述两个标志之一

  • [整理] Windows API 调用常量声明之按键篇

    常用键盘虚拟码声明.

  • [原创] 将REG文件转换成CMD/BAT文件(REG与CMD混合编程)

    批处理中经常需要使用注册表文件。一般的作法是使用命令 regedit /s 注册表文件.reg 其实根据.REG文件和.CMD文件的特性,可以合二为一。 .REG文件中;开头代表注释 .CMD文件中;开头并不影响执行。所以可以从这个方面入手。下面的注册表可以在右键菜单中添加一个MAKECAB项。

  • 【原创】批处理读取INI格式文件

    批处理读取INI文件,以前无聊时写的.当时只是觉得好玩就尝试写了一下,原贴请看DOS联盟论坛 http://www.cn-dos.net/forum/viewthread.php?tid=25789 最早的版本,发现了许多错误,而且使用了许多的SETLOCAL,经常会出错。后来优化了下,可以运行了,就一直都没有再去改过了。

  • 【测试】CQGhost 硬盘安装器

    基于Quick Ghost的一个应用 Quick Ghost 快速一键还原 CQGHOST Ghost硬盘安装器,可以在你熟悉的Windows环境下恢复GHO文件(设定还原参数,重启系统后自动恢复指定GHO),需要先自行复制GHO文件到硬盘上(位置随意,不要放在系统盘就可以了)

  • 批处理检测外部命令是否存在的模块

    编写批处理时经常需要用到外部命令,一些常用的命令一般的系统都会有,但是一些精简的系统上可能就没有了,如果没有做判断就可能导致程序出现未知的错误. 一般检测文件是否存在可以使用 IF EXIST filename 执行某个命令…

  • [转]批处理写的俄罗斯方块游戏

    绝对经典的批处理游戏!!! 本游戏需要三方choice.exe支持,请自行搜索下载 来源:批处理写的俄罗斯方块游戏

  • 使用批处理自动定时备份文件到邮箱

    因为需要,想让系统自动定时备份我的文件到邮箱上(只备份更新或新增加的文件),在网上找了许多软件要么是收费的,要么使用不方便.后来想起了以前收藏的一段 VBSCRIPT发送邮件的代码就想到是否可以利用批处理自己写一个脚本来实现,所以就有了以下的代码,有兴趣的朋友可以一起继续完善,现在只能根据文件大小,日期.来确定是否上传.

  • [转] Windows 下命令行/VBS脚本,发送带附件邮件.

    利用VBScript发送邮件,以前从网上找的代码,不知原来的出处了.也不知作者是何人….. 挺有用的脚本,我就一直在使用这个脚本来发邮件,还可以带附件.放在这里做个备份,免得到时又找不到了. 目前我就通过批处理配合这个脚本来自动备份我的一些文件到邮箱里面.每天自动定时备份.

  • 一键GHOST备份恢复,GHOST安装器设计新思路

    看起来可能有点乱^_^.实现起来也是挺麻烦的,暂时只是我的一个想法,仅供有兴趣的朋友研究尝试.放在这里做个记录,以后有兴趣再搞个成品. 最终的理想效果. 安装/卸载/使用方便简单,(只需改名复制或删除文件就可以了)

  • [分享]在CMD中使用位运算转换目标数字到二进制数.

    把一个十进制转成2进制的常分规方法是,一直除2求余. 这里介绍另一种方法, 一个把数值转换成二进制数的批处理脚本. 批处理加参数使用.支持把10,16,或8进制数转成二进制,其中16进制以0X开头,8进制以0开头.

  • [原创]网易邮箱通用自动登录批处理脚本[2010-05-23更新]

    网易邮箱自动登录批处理脚本.具体请看里面的使用说明. 可以自动登录网易邮箱.批处理调用. 使用方法: 直接在批处理里面输入用户名和密码. 使用命令行方加参数启动.第一个参数为用户名和邮箱名,第二个参数为密码

  • ASP函数语法速查表

    ASP函数语法速查表 Abs(数值)绝对值。一个数字的绝对值是它的正值。空字符串 (null) 的绝对值,也是空字符串。未初始化的变数,其绝对为 0例子:ABS(-2000) 结果:2000Array(以逗点分隔的数组元素)Array 函数传回数组元素的值。例子: A=Array(1,2,3) B=A(2) 结果: 2 说明:变量B为A数组的第二个元素的值。 Asc(字符串)将字符串的第一字母转换成 ANSI(美国国家标准符号)字码。例子:Asc("Internet") 结果:73 说明:显示第一字母 I 的 ANSI 字码。 CBool(表达式)转换成布尔逻辑值变量型态(True 或False)例子:CBool(1+2) 结果:True CDate(日期表达式)换成日期变量型态。可先使用 IsDate 函数判断是否可以转换成日 期。例子: CDate (now( )+2) 结果:2000/5/28 10:30:59 CDbl(表达式)转换成DOUBLE变量型态。Chr(ANSI 字码)将ASCII 字码转换成字符。例子: Chr(72) 结果: H CInt(表达式)转换成整数变量型态。例子: CInt (“3.12”) 结果: 3 CLng(表达式)转换成LONG 变量型态。CSng(表达式)转换成SINGLE 变量型态。CStr(表达式)转换成字符串变量型态。Date()传回系统的日期。例子: Date 结果: 2000/5/13DateAdd(I , N , D)将一个日期加上一段期间后的日期。 I :设定一个日期( Date)所加上的一段期间的单位。譬如 interval=”d” 表示 N的单位为日。 I的设定值如下: yyyy Year 年 q Quarter 季 m Month 月 d Day 日 w Weekday 星期 h Hour 时 n Minute 分 s Second 秒 N :数值表达式,设定一个日期所加上的一段期间,可为正值或负值,正值表示加(结果为 >date 以后的日期),负值表示减(结果为 >date 以前的日期)。 D :待加减的日期。例子: DateAdd(“m” , 1 , “31-Jan-98”) 结果: 28-Feb-98 说明:将日期 31-Jan-98 加上一个月,结果为 28-Feb-98 而非 31-Fe-98 。 例子: DateAdd(“d” , 20 , “30-Jan-99”) 结果: 1999/2/9 说明:将一个日期 30-Jan-99 加上 20 天后的日期。DateDiff (I , D1 , D2[,FW[,FY]])计算两个日期之间的期间。 I :设定两个日期之间的期间计算之单位。譬如 >I=”m” 表示计算的单位为月。 >I 的设定值如: yyyy > Year 年 q Quarter 季 m Month 月 d Day 日 w Weekday 星期 h Hour 时 m Minute 分 s Second 秒 D1 ,D2:计算期间的两个日期表达式,若 >date1 较早,则两个日期之间的期间结果为正值;若 >date2 较早, 则结果为负值。 FW :设定每周第一天为星期几, 若未设定表示为星期天。 >FW 的设定值如下: 0 使用 >API 的设定值。 1 星期天 2 星期一 3 星期二 4 星期三 5 星期四 6 星期五 7 星期六 FY :设定一年的第一周, 若未设定则表示一月一日那一周为一年的第一周。 >FY 的设定值如下: 0 使用 >API 的设定值。 1 一月一日那一周为一年的第一周 2 至少包括四天的第一周为一年的第一周 3 包括七天的第一周为一年的第一周例子: DateDiff (“d”,”25-Mar-99 “,”30-Jun-99 “) 结果: 97 说明:显示两个日期之间的期间为 97 天。DatePart (I,D,[,FW[,FY]])传回一个日期的之部份。 >I :设定传回那一部份。譬如 >I=”d” 表示传回 部份为日。 >I 的设定值如下: yyyy Year 年 q Quarter 季 m Month 月 d Day 日 w Weekday 星期 h Hour 时 m Minute 分 s Second 秒 D :待计算的日期。 >FW :设定每周第一天为星期几, 若未设定则表示为星期天。 >FW 的设定值如下: 0 使用 >API 的设定值。 1 星期天 2 星期一>3 星期二 4 星期三 5 星期四 6 星期五 7 星期六 FY :设定一年的第一周, 若未设定则表示一月一日那一周为一年的第一周。 >FY 的设定值如下: 0 使用 >API 的设定值。 1 一月一日那一周为一年的第一周 2 至少包括四天的第一周为一年的第一周 3 包括七天的第一周为一年的第一周例子: DatePart (“m”,”25-Mar-99 “) 结果: 3 说明:显示传回一个日期 的月部份。Dateserial (year,month,day)转换(year,month,day) 成日期变量型态。例子: DateSerial (99,10,1) 结果: 1999/10/1DateValue ( 日期的字符串或表达式 )转换成日期变量型态,日期从 January 1,100 到 December 31,9999 。格式为 month,day,and year 或 month/day/year 。譬如: December 30,1999 、 Dec 30,1999 、 12/30/1999 、 12/30/99例子: DateValue (“January 1,2002 “) 结果: 2002/1/1Day( 日期的字符串或表达式 )传回日期的「日」部份。例子: Day(“ 12/1/1999 “) 结果: 1Fix( 表达式 )转换字符串成整数数字型态。与 Int 函数相同。若为 null 时传回 null 。 Int (number) 与 Fix(number) 的差别在负数。如 Int (-5.6)=-6 , Fix(-5.6)=-5 。例子: Fix(5.6) 结果: 5Hex( 表达式 )传回数值的十六进制值。若表达式为 null 时 Hex( 表达式 )=null ,若表达式 =Empty 时 Hex( 表达式 )=0 。 16 进位可以加「 &H 」表示,譬如 16 进位 &H10 表示十进制的 16 。例子: Hex(30) 结果: 1EHour( 时间的字符串或表达式 )传回时间的「小时」部份。例子: Hour(“12:30:54 “) 结果: 12InStr ([start,]string1,string2[,compare]) 将一 个 字符串由左 而右与另一个比较,传回第一个相同的位置。 start 为从第几个字比较起,若省略 start 则从第一个字比较起, string1 为待寻找的字符串表达式, string2 为 待比较的字符串表达式, compare 为比较的方法, compare=0 表二进制比较法, compare=1 表文字比较法,若省略 compare 则为预设的二进制比较法。例子: InStr(“abc123def123”,”12”) 结果: 4InstrRev ([start,]string1,string2[,compare])将一 个 字符串 由右而左与另一个比较,传回第一个相同的位置。 start 为从第几个字比较起,若省略 start 则从第一个字比较起, string1 为待寻找的字符串表达式, string2 为 待比较的字符串表达式, compare 为比较的方法, compare=0 表二进制比较法, compare=1 表文字比较法,若省略 compare 则为预设的二进制比较法。例子: InstrRev (“abc123def123”,”12”) 结果: 10Int ( 表达式 )传回一个数值的整数部份。与 Fix 函数相同。例子: Int (5.6) 结果: 5IsArray ( 变数 )测试变量是 (True) 否 (False) 是一个数组。例子: IsArray (3) 结果: False 说明:不是一个数组。IsDate ( 日期或字符串的表达式 )是否可以转换成日期。日期从 January 1,100 A.D. 到 December 31,9999 A.D 。例子: IsDate (“December 31,1999 “) 结果: True 说明:可以转换成日期。IsEmpty ( 变数 )测试变量是 (True) 否 (False) 已经被初始化例子: IsEmpty (a) 结果: TrueIsNull ( 变数 )测试变数是 (True) 否 (False) 不是有效的数据。例子: IsNull (“”) 结果: False 说明:是有效的数据。IsNumeric ( 表达式 )是 (True) 否 (False) 是数字。例子: IsNumeric (“abc123”) 结果: False 说明:不是数字。LCase ( 字符串表达式 ) top转换字符串成小写。将大写字母的部份转换成小写。字符串其余的部份不变。例子: LCase (“ABC123”) 结果: abc123Left( 字符串表达式 ,length)取字符串左边的几个字。 length 为取个字。 Len 函数可得知字符串的长度。例子: Left(“ABC123”,3) 结果: ABCLen( 字符串表达式 变量 )取得字符串的长度。例子: Len(“ABC123”) 结果: 6LTrim ( 字符串表达式 )除去字符串左边的空白字。 RTrim 除去字符串右边的空白字, Trim 函数除去字符串左右两边的空白字。例子: LTrim (“456+” abc “) 结果: 456abc123Mid( 字符串表达式 ,start[,length]) 取字符串中的几个字。 start 为从第几个 字取起, length 为取几个字, 若略 length 则从 start 取到最右底。由Len 函数可得知字符串的长度。例子: Mid(“abc123”,2,3) 结果: c12Minute( 日期的字符串或表达式 )传回时间的「分钟」部份。例子: Minute(“12:30:54”) 结果:30Month(日期的字符串或表达式)传回日期的「月」部份。例子:Month(“12/1/2001”) 结果:12MonthName(month[,abbreviate])传回月的名称。 month :待传回月名称的数字 1~12 。譬如, 1 代表一月, 7 代表七月。 abbreviate: 是 (True) 否 (False) 为缩写,譬如 March ,缩写为 Mar 。默认值为 False 。中文的月名称无缩写。例子: MonthName (7) 结果:七月Now()传回系统的日期时间。例子: Now() 结果: 2001/12/30 10:35:59 AMOct()传回数值的八进位值。八进位可以加「 &O 」表示,譬如八进位 &O10 表示十进制的 8 。例子: Oct(10) 结果: 12Replace( 字符串表达式,findnreplacewith[,start[,count[,compare]]]) 将一个字符串取代 部份字。寻找待取代的原字符串 (find) , 若找到则被取代为新字符串 (replacewith) 。 find :待寻找取代的原字符串。 replacewith :取代后的字。 start :从第几个字开始寻找取代, 若未设定则由第一个字开始寻找。 count :取代的次数。 若未设定则所有寻找到的字符串取代字符 串全部被取代。 compare :寻找比较的方法, compare=0 表示二进制比较法, compare=1 表文字比较法, compare =2 表根据比较的 数据型态而定,若省略 compare 则为预设的二进制比较法。例子: Replace(“ABCD123ABC”,”AB”,”ab”) 结果: abCD123abCRight( 字符串表达式 ,length)取字符串右边的几个字, length 为取几个字。 Len 函数可得知字符串的长度。例子: Right(“ABC123”,3) 结果: 123Rnd [(number)]0~1 的 随机随机数值。 number 是任何有效的数值表达式。若 number 小于 0 表示每次得到相同的 随机随机数值。 number 大于 0 或未提供时表示依序得到下一个 随机随机数值。 >number=0 表示得到最近产生的 随机随机数值。为了避免得到相同的随机随机数顺序,可以于 Rnd 函数前加 Randomize 。例子: Rnd 结果: 0.498498Round( 数值表达式 [,D])四舍五入。 D :为四舍五入到第几位小数,若省略则四舍五入到整数。例子: Round(30635,1) 结果: 3.6RTrim ( 字符串表达式 )除去字符串右边的空白字。 LTrim 除去字符串左边的空白字, Trim 函数除去字符串左右两边的空白字。例子: RTrim (“abc123 “)+”456” 结果: abc123456Second( 时间的字符串或表达式 )传回时间的「秒」部份。例子:Second(“12:30:54”) 结果:54Space( 重复次数 )得到重复相同的空白字符串。例子: A”+Space (5)+”B 结果: A B 说明: A 和 B 中间加入五个空白字。String( 重复次数,待重复的字 )得到重复相同的字符串。例子: String(5,71) 结果: GGGGGStrReverse (String(10,71))将一个字符串顺序颠倒。例子: StrReverse (“ABC”) 结果: CBATime()传回系统的时间。例子: Time 结果: 10:35:59 PMTimeSerial (hour,minute,second)转换指定的 ( hour,minute,second) 成时间 变量型态。例子: TimeSerial (10,31,59) 结果: 10:31:59TimeValue ( 日期的字符串或表达式 )转换 成时间变量型态。日期的字符串或表达式从 0:00:00(12:00:00 A.M.) 到 23:59:59(11:59:59 P.M.) 。例子: TimeValue (“ 11:59:59 “) 结果: 11:59:59Trim( 字符串表达式 )除去字符串左右两边的空白字。例子: Trim(“ abc123 “) 结果: abc123UCase ()转换字符串成大写。将小写字母的部份转换成大写,字符串其余部份不变。例子: UCase (“abc123”) 结果: ABC123VarType ( 变数 )传回一个变量类型。与 TypeName 函数相同, VarType 传回变量类型的代码, TypeName 传回变量类型的名称。例子: VarType ( “I love you!”) 结果: 8Weekday( 日期表达式 ,[FW]) 传回星期几的数字。 FW :设定一周的第一天是星期几。若 省略则表 1( 星期日 ) 。 Firstdayfweek 设定值为: 1( 星期日 ),2( 星期一 ),3( 星期二 ),4( 星期三 ),5( 星期四 ),6( 星期五 ),7( 星期六 ) 。例子: Weekday(“ 1/1/2000”) 结果: 7WeekDayName (W,A,FW)传回星期几的名称。 W :是 (True) 否 (False) 为缩写。譬如 March ,缩写为 Mar 。预设为 False 。中文的星期几名称无缩写。 FW :设定一周的第一天是星期几。 若省略表 1( 星期日 ) 。设定待传回星期几的名称,为一周中的第几天。 A : 1( 星期日 ),2( 星期一 ),3( 星期二 ),4( 星期三 ),5( 星期四 ),6( 星期五 ),7( 星期六 ) 。例子: WeekDayName (“1/1/2000”) 结果:星期六Year()传回日期的「年」部份。例子: Year(“ 12/1/2000 “) 结果: 2000

  • [转]正则表达式30分钟入门教程

    30分钟内让你明白正则表达式是什么,并对它有一些基本的了解,让你可以在自己的程序或网页里使用它。

  • [原创]QGHO 快速一键恢复程序(2011-01-02更新)

    [说明] QGHO是一个用于演示GRUB4DOS功能的小程序. 可以快速全自动/手动 备份恢复分区.(使用GHOST内核). 目前为止最快速/最小巧的基于DOS+GHOST的备份恢复程序. BUG报告或其它资料请移步我的搏客 http://chenall.net/post/qgho/

  • C语言的基础函数大小写转换

    在程序中经常会需要对字母的大小写进行转换,虽然有现成的upper/lower函数,但是有时因为各种原因,或想减小程序的体积,需要自己编写函数来实现。 这里来讨论一下各种转换的方法。 根据ASCII码我们可以知道大写字母和小写字母相差32(20H)=100000B(二进制).

  • [原创] 也来谈谈经典游戏贪吃蛇的简易设计思路

    注:原创方案,如有雷同纯属巧合. 本人对图形系统并不感冒.不喜欢也不会设计图形.所以本文介绍的也只会有简单的界面. 突然有了一些灵感,所以就把它记录下来,并尝试用代码来实现它. 当然了它不是拿来玩的而是用于学习,呵呵.

  • [原创] 无聊贴一段代码

    快速计算某个POS软件的员工密码… 使用批处理计算快速简单. ^_^ 至少有N+X个密码可以用哦. 不想解释. 谁用谁知道 . 嘿黑,别做坏事哦. ==================================================

  • [转] 遍历PCI设备

    先来一段废话: 消化一下,准备自己也来写一个SCANPCI程序,不过不是在DOS下使用,而是在GRUB4DOS下使用. 根据netwinxp的汇编程序CHKPCI程序(第二个链接的后面)和这篇文章,消化了一些,目前可以简单显示当前PCI设备列表,还是有很多东西不是很明白,有空慢慢消化.顺便学点汇编知识.

  • 分布式查询

    分布式查询从多异类数据源中访问数据。这些数据源可以存储在同一台计算机或不同的计算机上。Microsoft SQL Server 通过使用 OLE DB 来支持分布式查询。 SQL Server 用户可以使用分布式查询访问以下内容:

  • FAT 文件系统原理

    研究FAT文件系统的好文. 来源:http://www.sjhf.net/Article/Index.html 如果看不到请点击以下链接查看 FAT 文件系统原理

  • 将数据输出到Excel的方法

    日常工作中经常需要把某一部份数据导出到EXCEL,通常情况都有软件提供类似方案. 但是这需要手工去打开软件然后导出,不能实现自动化.所以就编写了这个脚本方便实现自动化. 本脚本采用VBSCRIPT语言编写.可以在VB或VBS脚本中使用.

  • [整理] 汇编几个重要内存单元地址

    本附录按类列举出一些重要的系统信息在内存中物理地址,为直接访问内存读取相应信息提供方便。 了解的内容:了解计算机系统的一些重要信息在内存中的存放位置。需要时,可直接访问内存读取相应信息。 本附录主要用于查阅,当使用时,知道在本附录中查阅。

  • [原创] VHD_MNT VHD文件快速挂载/卸载工具

    VHD_MNT 是使用批处理写的一个小程序 , 可以在WIN7以上的系统中使用. 用于快速挂载/卸载VHD虚拟磁盘. 依赖程序: 系统自带的diskpart,reg,find三个命令. 特点: 不使用第三方工具,不生成临时文件.使用方便.你需要做的只是双击.

  • [分享] 在使用批处理修改WINDOWS的打印机设置

    因为无忧里面以下贴子, http://bbs.wuyou.com/viewthread.php?tid=187450 所以就抽空研究了一下整理了一个批处理出来. 自己目前用不上,发在这里留一个底,万一自己以后碰到了就有现成的可用了.

  • [转]Linux 汇编语言开发指南

    汇编语言的优点是速度快,可以直接对硬件进行操作,这对诸如图形处理等关键应用是非常重要的。Linux 是一个用 C 语言开发的操作系统,这使得很多程序员开始忘记在 Linux 中还可以直接使用汇编这一底层语言来优化程序的性能。本文为那些在Linux 平台上编写汇编代码的程序员提供指南,介绍 Linux 汇编语言的语法格式和开发工具,并辅以具体的例子讲述如何开发实用的Linux 汇编程序。一、简介作为最基本的编程语言之一,汇编语言虽然应用的范围不算很广,但重要性却勿庸置疑,因为它能够完成许多其它语言所无法完成的功能。就拿 Linux 内核来讲,虽然绝大部分代码是用 C 语言编写的,但仍然不可避免地在某些关键地方使用了汇编代码,其中主要是在 Linux 的启动部分。由于这部分代码与硬件的关系非常密切,即使是 C 语言也会有些力不从心,而汇编语言则能够很好扬长避短,最大限度地发挥硬件的性能。大多数情况下 Linux 程序员不需要使用汇编语言,因为即便是硬件驱动这样的底层程序在 Linux 操作系统中也可以用完全用 C 语言来实现,再加上 GCC 这一优秀的编译器目前已经能够对最终生成的代码进行很好的优化,的确有足够的理由让我们可以暂时将汇编语言抛在一边了。但实现情况是 Linux 程序员有时还是需要使用汇编,或者不得不使用汇编,理由很简单:精简、高效和 libc 无关性。假设要移植 Linux 到某一特定的嵌入式硬件环境下,首先必然面临如何减少系统大小、提高执行效率等问题,此时或许只有汇编语言能帮上忙了。汇编语言直接同计算机的底层软件甚至硬件进行交互,它具有如下一些优点:· 能够直接访问与硬件相关的存储器或 I/O 端口;· 能够不受编译器的限制,对生成的二进制代码进行完全的控制;· 能够对关键代码进行更准确的控制,避免因线程共同访问或者硬件设备共享引起的死锁;· 能够根据特定的应用对代码做最佳的优化,提高运行速度;· 能够最大限度地发挥硬件的功能。同时还应该认识到,汇编语言是一种层次非常低的语言,它仅仅高于直接手工编写二进制的机器指令码,因此不可避免地存在一些缺点:· 编写的代码非常难懂,不好维护;· 很容易产生 bug,难于调试;· 只能针对特定的体系结构和处理器进行优化;· 开发效率很低,时间长且单调。Linux 下用汇编语言编写的代码具有两种不同的形式。第一种是完全的汇编代码,指的是整个程序全部用汇编语言编写。尽管是完全的汇编代码,Linux 平台下的汇编工具也吸收了 C 语言的长处,使得程序员可以使用 #include、#ifdef 等预处理指令,并能够通过宏定义来简化代码。第二种是内嵌的汇编代码,指的是可以嵌入到C语言程序中的汇编代码片段。虽然 ANSI 的 C 语言标准中没有关于内嵌汇编代码的相应规定,但各种实际使用的 C 编译器都做了这方面的扩充,这其中当然就包括 Linux 平台下的 GCC。二、Linux 汇编语法格式绝大多数 Linux 程序员以前只接触过DOS/Windows 下的汇编语言,这些汇编代码都是 Intel 风格的。但在 Unix 和 Linux 系统中,更多采用的还是 AT&T 格式,两者在语法格式上有着很大的不同:在 AT&T 汇编格式中,寄存器名要加上 ‘%’ 作为前缀;而在 Intel 汇编格式中,寄存器名不需要加前缀。例如:AT&T 格式Intel 格式pushl %eaxpush eax在 AT&T 汇编格式中,用 ‘$’ 前缀表示一个立即操作数;而在 Intel 汇编格式中,立即数的表示不用带任何前缀。例如:AT&T 格式Intel 格式pushl $1push 1AT&T 和 Intel 格式中的源操作数和目标操作数的位置正好相反。在 Intel 汇编格式中,目标操作数在源操作数的左边;而在 AT&T 汇编格式中,目标操作数在源操作数的右边。例如:AT&T 格式Intel 格式addl $1, %eaxadd eax, 1在 AT&T 汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀‘b’、‘w’、‘l’分别表示操作数为字节(byte,8 比特)、字(word,16 比特)和长字(long,32比特);而在 Intel 汇编格式中,操作数的字长是用 “byte ptr” 和 “word ptr” 等前缀来表示的。例如:AT&T 格式Intel 格式movb val, %almov al, byte ptr val在 AT&T 汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上‘*’作为前缀,而在 Intel 格式中则不需要。远程转移指令和远程子调用指令的操作码,在 AT&T 汇编格式中为 “ljump” 和 “lcall”,而在 Intel 汇编格式中则为 “jmp far” 和 “call far”,即:AT&T 格式Intel 格式ljump $section, $offsetjmp far section:offsetlcall $section, $offsetcall far section:offset与之相应的远程返回指令则为:AT&T 格式Intel 格式lret $stack_adjustret far stack_adjust在 AT&T 汇编格式中,内存操作数的寻址方式是section:disp(base, index, scale)而在 Intel 汇编格式中,内存操作数的寻址方式为:section:[base + index*scale + disp]由于 Linux 工作在保护模式下,用的是 32 位线性地址,所以在计算地址时不用考虑段基址和偏移量,而是采用如下的地址计算方法:disp + base + index * scale下面是一些内存操作数的例子:AT&T 格式Intel 格式movl -4(%ebp), %eaxmov eax, [ebp - 4]movl array(, %eax, 4), %eaxmov eax, [eax*4 + array]movw array(%ebx, %eax, 4), %cxmov cx, [ebx + 4*eax + array]movb $4, %fs:(%eax)mov fs:eax, 4三、Hello World!真不知道打破这个传统会带来什么样的后果,但既然所有程序设计语言的第一个例子都是在屏幕上打印一个字符串 “Hello World!”,那我们也以这种方式来开始介绍 Linux 下的汇编语言程序设计。在 Linux 操作系统中,你有很多办法可以实现在屏幕上显示一个字符串,但最简洁的方式是使用 Linux 内核提供的系统调用。使用这种方法最大的好处是可以直接和操作系统的内核进行通讯,不需要链接诸如 libc 这样的函数库,也不需要使用 ELF 解释器,因而代码尺寸小且执行速度快。Linux 是一个运行在保护模式下的 32 位操作系统,采用 flat memory 模式,目前最常用到的是 ELF 格式的二进制代码。一个 ELF 格式的可执行程序通常划分为如下几个部分:.text、.data 和 .bss,其中 .text 是只读的代码区,.data 是可读可写的数据区,而 .bss 则是可读可写且没有初始化的数据区。代码区和数据区在 ELF 中统称为 section,根据实际需要你可以使用其它标准的 section,也可以添加自定义 section,但一个 ELF 可执行程序至少应该有一个 .text 部分。下面给出我们的第一个汇编程序,用的是 AT&T 汇编语言格式:例1. AT&T 格式#hello.s .data                    # 数据段声明        msg : .string ”Hello, world!\\n” # 要输出的字符串        len = . - msg                   # 字串长度.text                    # 代码段声明.global _start           # 指定入口函数        _start:                  # 在屏幕上显示一个字符串        movl $len, %edx  # 参数三:字符串长度        movl $msg, %ecx  # 参数二:要显示的字符串        movl $1, %ebx    # 参数一:文件描述符(stdout)         movl $4, %eax    # 系统调用号(sys_write)         int  $0×80       # 调用内核功能                                 # 退出程序        movl $0,%ebx     # 参数一:退出代码        movl $1,%eax     # 系统调用号(sys_exit)         int  $0×80       # 调用内核功能初次接触到 AT&T 格式的汇编代码时,很多程序员都认为太晦涩难懂了,没有关系,在 Linux 平台上你同样可以使用 Intel 格式来编写汇编程序:例2. Intel 格式; hello.asm section .data            ; 数据段声明        msg db ”Hello, world!”, 0xA     ; 要输出的字符串        len equ $ - msg                 ; 字串长度section .text            ; 代码段声明global _start            ; 指定入口函数_start:                  ; 在屏幕上显示一个字符串        mov edx, len     ; 参数三:字符串长度        mov ecx, msg     ; 参数二:要显示的字符串        mov ebx, 1       ; 参数一:文件描述符(stdout)         mov eax, 4       ; 系统调用号(sys_write)         int 0×80         ; 调用内核功能                         ; 退出程序        mov ebx, 0       ; 参数一:退出代码        mov eax, 1       ; 系统调用号(sys_exit)         int 0×80         ; 调用内核功能上面两个汇编程序采用的语法虽然完全不同,但功能却都是调用 Linux 内核提供的 sys_write 来显示一个字符串,然后再调用 sys_exit 退出程序。在 Linux 内核源文件 include/asm-i386/unistd.h 中,可以找到所有系统调用的定义。四、Linux 汇编工具Linux 平台下的汇编工具虽然种类很多,但同 DOS/Windows 一样,最基本的仍然是汇编器、连接器和调试器。1.汇编器汇编器(assembler)的作用是将用汇编语言编写的源程序转换成二进制形式的目标代码。Linux 平台的标准汇编器是 GAS,它是 GCC 所依赖的后台汇编工具,通常包含在 binutils 软件包中。GAS 使用标准的 AT&T 汇编语法,可以用来汇编用 AT&T 格式编写的程序:[xiaowp@gary code]$ as -o hello.o hello.sLinux 平台上另一个经常用到的汇编器是 NASM,它提供了很好的宏指令功能,并能够支持相当多的目标代码格式,包括 bin、a.out、coff、elf、rdf 等。NASM 采用的是人工编写的语法分析器,因而执行速度要比 GAS 快很多,更重要的是它使用的是 Intel 汇编语法,可以用来编译用 Intel 语法格式编写的汇编程序:[xiaowp@gary code]$ nasm -f elf hello.asm2.链接器由汇编器产生的目标代码是不能直接在计算机上运行的,它必须经过链接器的处理才能生成可执行代码。链接器通常用来将多个目标代码连接成一个可执行代码,这样可以先将整个程序分成几个模块来单独开发,然后才将它们组合(链接)成一个应用程序。 Linux 使用 ld 作为标准的链接程序,它同样也包含在 binutils 软件包中。汇编程序在成功通过 GAS 或 NASM 的编译并生成目标代码后,就可以使用 ld 将其链接成可执行程序了:[xiaowp@gary code]$ ld -s -o hello hello.o3.调试器有人说程序不是编出来而是调出来的,足见调试在软件开发中的重要作用,在用汇编语言编写程序时尤其如此。Linux 下调试汇编代码既可以用 GDB、DDD 这类通用的调试器,也可以使用专门用来调试汇编代码的 ALD(Assembly Language Debugger)。从调试的角度来看,使用 GAS 的好处是可以在生成的目标代码中包含符号表(symbol table),这样就可以使用 GDB 和 DDD 来进行源码级的调试了。要在生成的可执行程序中包含符号表,可以采用下面的方式进行编译和链接:[xiaowp@gary code]$ as –gstabs -o hello.o hello.s[xiaowp@gary code]$ ld -o hello hello.o执行 as 命令时带上参数 –gstabs 可以告诉汇编器在生成的目标代码中加上符号表,同时需要注意的是,在用 ld 命令进行链接时不要加上 -s 参数,否则目标代码中的符号表在链接时将被删去。在 GDB 和 DDD 中调试汇编代码和调试 C 语言代码是一样的,你可以通过设置断点来中断程序的运行,查看变量和寄存器的当前值,并可以对代码进行单步跟踪。图1 是在 DDD 中调试汇编代码时的情景:图1 用 DDD 中调试汇编程序汇编程序员通常面对的都是一些比较苛刻的软硬件环境,短小精悍的ALD可能更能符合实际的需要,因此下面主要介绍一下如何用ALD来调试汇编程序。首先在命令行方式下执行ald命令来启动调试器,该命令的参数是将要被调试的可执行程序:[xiaowp@gary doc]$ ald helloAssembly Language Debugger 0.1.3Copyright (C) 2000-2002 Patrick Alkenhello: ELF Intel 80386 (32 bit), LSB, Executable, Version 1 (current)Loading debugging symbols…(15 symbols loaded)ald>当 ALD 的提示符出现之后,用 disassemble 命令对代码段进行反汇编:ald> disassemble -s .textDisassembling section .text (0×08048074 - 0×08048096)08048074  BA0F000000                 mov edx, 0xf08048079  B998900408                 mov ecx, 0×80490980804807E  BB01000000                 mov ebx, 0×108048083  B804000000                 mov eax, 0×408048088  CD80                       int 0×800804808A  BB00000000                 mov ebx, 0×00804808F  B801000000                 mov eax, 0×108048094  CD80                       int 0×80上述输出信息的第一列是指令对应的地址码,利用它可以设置在程序执行时的断点:ald> break 0×08048088Breakpoint 1 set for 0×08048088断点设置好后,使用 run 命令开始执行程序。ALD 在遇到断点时将自动暂停程序的运行,同时会显示所有寄存器的当前值:ald> runStarting program: helloBreakpoint 1 encountered at 0×08048088eax = 0×00000004 ebx = 0×00000001 ecx = 0×08049098 edx = 0x0000000Fesp = 0xBFFFF6C0 ebp = 0×00000000 esi = 0×00000000 edi = 0×00000000ds  = 0x0000002B es  = 0x0000002B fs  = 0×00000000 gs  = 0×00000000ss  = 0x0000002B cs  = 0×00000023 eip = 0×08048088 eflags = 0×00000246Flags: PF ZF IF08048088  CD80                       int 0×80如果需要对汇编代码进行单步调试,可以使用 next 命令:ald> nextHello, world!eax = 0x0000000F ebx = 0×00000000 ecx = 0×08049098 edx = 0x0000000Fesp = 0xBFFFF6C0 ebp = 0×00000000 esi = 0×00000000 edi = 0×00000000ds  = 0x0000002B es  = 0x0000002B fs  = 0×00000000 gs  = 0×00000000ss  = 0x0000002B cs  = 0×00000023 eip = 0x0804808F eflags = 0×00000346Flags: PF ZF TF IF0804808F  B801000000                 mov eax, 0×1若想获得 ALD 支持的所有调试命令的详细列表,可以使用 help 命令:ald> helpCommands may be abbreviated.If a blank command is entered, the last command is repeated.Type `help <command>’ for more specific information on <command>.General commandsattach         clear          continue       detach         disassembleenter          examine        file           help           loadnext           quit           register       run            setstep           unload         window         writeBreakpoint related commandsbreak          delete         disable        enable         ignorelbreak         tbreak五、系统调用即便是最简单的汇编程序,也难免要用到诸如输入、输出以及退出等操作,而要进行这些操作则需要调用操作系统所提供的服务,也就是系统调用。除非你的程序只完成加减乘除等数学运算,否则将很难避免使用系统调用,事实上除了系统调用不同之外,各种操作系统的汇编编程往往都是很类似的。在 Linux 平台下有两种方式来使用系统调用:利用封装后的 C 库(libc)或者通过汇编直接调用。其中通过汇编语言来直接调用系统调用,是最高效地使用 Linux 内核服务的方法,因为最终生成的程序不需要与任何库进行链接,而是直接和内核通信。和 DOS 一样,Linux 下的系统调用也是通过中断(int 0×80)来实现的。在执行 int 80 指令时,寄存器 eax 中存放的是系统调用的功能号,而传给系统调用的参数则必须按顺序放到寄存器 ebx,ecx,edx,esi,edi 中,当系统调用完成之后,返回值可以在寄存器 eax 中获得。所有的系统调用功能号都可以在文件 /usr/include/bits/syscall.h 中找到,为了便于使用,它们是用 SYS_<name> 这样的宏来定义的,如 SYS_write、SYS_exit 等。例如,经常用到的 write 函数是如下定义的:ssize_t write(int fd, const void *buf, size_t count);该函数的功能最终是通过 SYS_write 这一系统调用来实现的。根据上面的约定,参数 fb、buf 和 count 分别存在寄存器 ebx、ecx 和 edx 中,而系统调用号 SYS_write 则放在寄存器 eax 中,当 int 0×80 指令执行完毕后,返回值可以从寄存器 eax 中获得。或许你已经发现,在进行系统调用时至多只有 5 个寄存器能够用来保存参数,难道所有系统调用的参数个数都不超过 5 吗?当然不是,例如 mmap 函数就有 6 个参数,这些参数最后都需要传递给系统调用 SYS_mmap:void  *  mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);当一个系统调用所需的参数个数大于 5 时,执行int 0×80 指令时仍需将系统调用功能号保存在寄存器 eax 中,所不同的只是全部参数应该依次放在一块连续的内存区域里,同时在寄存器 ebx 中保存指向该内存区域的指针。系统调用完成之后,返回值仍将保存在寄存器 eax 中。由于只是需要一块连续的内存区域来保存系统调用的参数,因此完全可以像普通的函数调用一样使用栈(stack)来传递系统调用所需的参数。但要注意一点,Linux 采用的是 C 语言的调用模式,这就意味着所有参数必须以相反的顺序进栈,即最后一个参数先入栈,而第一个参数则最后入栈。如果采用栈来传递系统调用所需的参数,在执行int 0×80 指令时还应该将栈指针的当前值复制到寄存器 ebx中。六、命令行参数在 Linux 操作系统中,当一个可执行程序通过命令行启动时,其所需的参数将被保存到栈中:首先是 argc,然后是指向各个命令行参数的指针数组 argv,最后是指向环境变量的指针数据 envp。在编写汇编语言程序时,很多时候需要对这些参数进行处理,下面的代码示范了如何在汇编代码中进行命令行参数的处理:例3. 处理命令行参数# args.s//有些不明白.text.globl _start        _start:        popl    %ecx        # argcvnext:        popl    %ecx        # argv          test    %ecx, %ecx      # 空指针表明结束        jz  exit        movl    %ecx, %ebx        xorl    %edx, %edxstrlen:        movb    (%ebx), %al        inc %edx        inc %ebx        test    %al, %al        jnz strlen        movb    $10, -1(%ebx)        movl    $4, %eax        # 系统调用号(sys_write)         movl    $1, %ebx        # 文件描述符(stdout)         int $0×80        jmp vnextexit:        movl    $1,%eax         # 系统调用号(sys_exit)         xorl    %ebx, %ebx      # 退出代码        int     $0×80      ret七、GCC 内联汇编用汇编编写的程序虽然运行速度快,但开发速度非常慢,效率也很低。如果只是想对关键代码段进行优化,或许更好的办法是将汇编指令嵌入到 C 语言程序中,从而充分利用高级语言和汇编语言各自的特点。但一般来讲,在 C 代码中嵌入汇编语句要比“纯粹“的汇编语言代码复杂得多,因为需要解决如何分配寄存器,以及如何与C代码中的变量相结合等问题。GCC 提供了很好的内联汇编支持,最基本的格式是:__asm__(“asm statements”);例如:__asm__(“nop”); 如果需要同时执行多条汇编语句,则应该用“\\n\\t”将各个语句分隔开,例如:__asm__( ”pushl %%eax \\n\\t”         ”movl $0, %%eax \\n\\t”         ”popl %eax”);通常嵌入到 C 代码中的汇编语句很难做到与其它部分没有任何关系,因此更多时候需要用到完整的内联汇编格式:__asm__(“asm statements” : outputs : inputs : registers-modified);插入到 C 代码中的汇编语句是以“:”分隔的四个部分,其中第一部分就是汇编代码本身,通常称为指令部,其格式和在汇编语言中使用的格式基本相同。指令部分是必须的,而其它部分则可以根据实际情况而省略。在将汇编语句嵌入到C代码中时,操作数如何与C代码中的变量相结合是个很大的问题。GCC采用如下方法来解决这个问题:程序员提供具体的指令,而对寄存器的使用则只需给出“样板“和约束条件就可以了,具体如何将寄存器与变量结合起来完全由GCC和GAS来负责。在GCC内联汇编语句的指令部中,加上前缀‘%’的数字(如%0,%1)表示的就是需要使用寄存器的“样板“操作数。指令部中使用了几个样板操作数,就表明有几个变量需要与寄存器相结合,这样GCC和GAS在编译和汇编时会根据后面给定的约束条件进行恰当的处理。由于样板操作数也使用‘%’作为前缀,因此在涉及到具体的寄存器时,寄存器名前面应该加上两个‘%’,以免产生混淆。紧跟在指令部后面的是输出部,是规定输出变量如何与样板操作数进行结合的条件,每个条件称为一个“约束“,必要时可以包含多个约束,相互之间用逗号分隔开就可以了。每个输出约束都以‘=’号开始,然后紧跟一个对操作数类型进行说明的字后,最后是如何与变量相结合的约束。凡是与输出部中说明的操作数相结合的寄存器或操作数本身,在执行完嵌入的汇编代码后均不保留执行之前的内容,这是GCC在调度寄存器时所使用的依据。输出部后面是输入部,输入约束的格式和输出约束相似,但不带‘=’号。如果一个输入约束要求使用寄存器,则GCC在预处理时就会为之分配一个寄存器,并插入必要的指令将操作数装入该寄存器。与输入部中说明的操作数结合的寄存器或操作数本身,在执行完嵌入的汇编代码后也不保留执行之前的内容。有时在进行某些操作时,除了要用到进行数据输入和输出的寄存器外,还要使用多个寄存器来保存中间计算结果,这样就难免会破坏原有寄存器的内容。在GCC内联汇编格式中的最后一个部分中,可以对将产生副作用的寄存器进行说明,以便GCC能够采用相应的措施。下面是一个内联汇编的简单例子:例4.内联汇编/* inline.c */int main(){    int a = 10, b = 0;    __asm__ __volatile__(“movl %1, %%eax;\\n\\r”                         ”movl %%eax, %0;”                         :”=r”(b)      /* 输出 */                             :”r”(a)       /* 输入 */                         :”%eax”);     /* 受影响的寄存器 */        printf(“Result: %d, %d\\n”, a, b);}上面的程序完成将变量a的值赋予变量b,有几点需要说明:· 变量b是输出操作数,通过%0来引用,而变量a是输入操作数,通过%1来引用。· 输入操作数和输出操作数都使用r进行约束,表示将变量a和变量b存储在寄存器中。输入约束和输出约束的不同点在于输出约束多一个约束修饰符‘=’。· 在内联汇编语句中使用寄存器eax时,寄存器名前应该加两个‘%’,即%%eax。内联汇编中使用%0、%1等来标识变量,任何只带一个‘%’的标识符都看成是操作数,而不是寄存器。· 内联汇编语句的最后一个部分告诉GCC它将改变寄存器eax中的值,GCC在处理时不应使用该寄存器来存储任何其它的值。· 由于变量b被指定成输出操作数,当内联汇编语句执行完毕后,它所保存的值将被更新。在内联汇编中用到的操作数从输出部的第一个约束开始编号,序号从0开始,每个约束记数一次,指令部要引用这些操作数时,只需在序号前加上‘%’作为前缀就可以了。需要注意的是,内联汇编语句的指令部在引用一个操作数时总是将其作为32位的长字使用,但实际情况可能需要的是字或字节,因此应该在约束中指明正确的限定符:限定符意义“m”、“v”、“o”内存单元“r”任何寄存器“q”寄存器eax、ebx、ecx、edx之一“i”、“h”直接操作数“E”和“F”浮点数“g”任意“a”、“b”、“c”、“d”分别表示寄存器eax、ebx、ecx和edx“S”和“D”寄存器esi、edi“I”常数(0至31) 1。”m”:操作数是内存变量。         2。”o”:操作数是内存变量,但它的寻址方式必须是“偏移量”类型的,      也就是基址寻址或者基址加变址寻址。         3。”V”:操作数是内存变量,其寻址方式非“偏移量”类型。         4。”   ”:操作数是内存变量,其地址自动增量。         6。”r”:操作数是通用寄存器。         7。”i”:操作数是立即操作数。(其值可在汇编时确定)         8。”n”:操作数是立即操作数。有些系统不支持除字(双字节)以外的      立即操作数,这些操作数要用”n”而不是”i”来描述。         9。”g”:操作数可以是立即数,内存变量或者寄存器,只要寄存器属      于通用寄存器。         10。”X”:操作数允许是任何类型。         11。”0″,”1″,…,”9″:操作数与某个指定的操作数匹配。也就是说,      该操作数就是指定的那个操作数。例如,如果用”0″来描述”%1″操作      数,那么”%1″引用的其实就是”%0″操作数。         12。”p”:操作数是一个合法的内存地址(指针)。         13。”=”:操作数在指令中是只写的(输出操作数)。         14。”+”:操作数在指令中是读-写类型的(输入-输出操作数)。         15。”a”:寄存器EAX。         16。”b”:寄存器EBX。         17。”c”:寄存器ECX。         18。”d”:寄存器EDX。         19。”q”:寄存器”a”,”b”,”c”或者”d”。         20。”A”:寄存器”a”或者”d”。         21。”a”:寄存器EAX。         22。”f”:浮点数寄存器。         23。”t”:第一个浮点数寄存器。         24。”u”:第二个浮点数寄存器。         25。”D”:寄存器di。         26。”S”:寄存器si。         27。”I”:0-31之间的立即数。(用于32位的移位指令)         28。”J”:0-63之间的立即数。(用于64位的移位指令)         29。”N”:0-255之间的立即数。(用于”out”指令)         30。”G”:标准的80387浮点常数。    八、小结Linux操作系统是用C语言编写的,汇编只在必要的时候才被人们想到,但它却是减少代码尺寸和优化代码性能的一种非常重要的手段,特别是在与硬件直接交互的时候,汇编可以说是最佳的选择。Linux提供了非常优秀的工具来支持汇编程序的开发,使用GCC的内联汇编能够充分地发挥C语言和汇编语言各自的优点。参考资料1 在网站 http://linuxassembly.org上可以找到大量的Linux汇编资源。2 软件包binutils提供了as和ld等实用工具,其相关信息可以在网站 http://sources.redhat.com/binutils/上找到。3 NASM是Intel格式的汇编器,其相关信息可以在网站 http://nasm.sourceforge.net上找到。4 ALD是一个短小精悍的汇编调试器,其相关信息可以在网站 http://dunx1.irt.drexel.edu/~psa22/ald.html上找到。5 intel2gas是一个能够将Intel汇编格式转换成AT&T汇编格式的小工具,其相关信息可以在网站 http://www.niksula.cs.hut.fi/~mtiihone/intel2gas/上找到。6 IBM developerWorks上有一篇介绍GCC内联汇编的文章( http://www.ibm.com/developerworks/cn/linux/sdk/assemble/inline/index.shtml)。7 本文代码下载: 代码。GAS中每个操作都是有一个字符的后缀,表明操作数的大小。C声明GAS后缀大小(字节)charb1shortw2(unsigned) int / long / char*l4floats4doublel8long doublet10/12注意:GAL使用后缀“l”同时表示4字节整数和8字节双精度浮点数,这不会产生歧义因为浮点数使用的是完全不同的指令和寄存器。操作数格式:格式操作数值名称样例(GAS = C语言)$ImmImm立即数寻址$1 = 1EaR[Ea]寄存器寻址%eax = eaxImmM[Imm]绝对寻址0×104 = *0×104(Ea)M[R[Ea]]间接寻址(%eax)= *eaxImm(Ea)M[Imm+R[Ea]](基址+偏移量)寻址4(%eax) = *(4+eax)(Ea,Eb)M[R[Ea]+R[Eb]]变址(%eax,%ebx) = *(eax+ebx)Imm(Ea,Eb)M[Imm+R[Ea]+R[Eb]]寻址9(%eax,%ebx)= *(9+eax+ebx)(,Ea,s)M[R[Ea]*s]伸缩化变址寻址(,%eax,4)= *(eax*4)Imm(,Ea,s)M[Imm+R[Ea]*s]伸缩化变址寻址0xfc(,%eax,4)= *(0xfc+eax*4)(Ea,Eb,s)M(R[Ea]+R[Eb]*s)伸缩化变址寻址(%eax,%ebx,4) = *(eax+ebx*4)Imm(Ea,Eb,s)M(Imm+R[Ea]+R[Eb]*s)伸缩化变址寻址8(%eax,%ebx,4) = *(8+eax+ebx*4)注:M[xx]表示在存储器中xx地址的值,R[xx]表示寄存器xx的值,这种表示方法将寄存器、内存都看出一个大数组的形式。数据传送指令:指令效果描述movl S,DD <– S传双字movw S,DD <– S传字movb S,DD <– S传字节movsbl S,DD <– 符号扩展S符号位填充(字节->双字)movzbl S,DD <– 零扩展S零填充(字节->双字)pushl SR[%esp] <– R[%esp] – 4;M[R[%esp]] <– S压栈popl DD <– M[R[%esp]];R[%esp] <– R[%esp] + 4;出栈注:均假设栈往低地址扩展。算数和逻辑操作地址:指令效果描述leal S,DD = &Smovl地版,S地址入D,D仅能是寄存器incl DD++加1decl DD–减1negl DD = -D取负notl DD = ~D取反addl S,DD = D + S加subl S,DD = D – S减imull S,DD = D*S乘xorl S,DD = D ^ S异或orl S,DD = D | S或andl S,DD = D & S与sall k,DD = D << k左移shll k,DD = D << k左移(同sall)sarl k,DD = D >> k算数右移shrl k,DD = D >> k逻辑右移特殊算术操作:指令效果描述imull SR[%edx]:R[%eax] = S * R[%eax]无符号64位乘mull SR[%edx]:R[%eax] = S * R[%eax]有符号64位乘cltd SR[%edx]:R[%eax] = 符号位扩展R[%eax]转换为4字节idivl SR[%edx] = R[%edx]:R[%eax] % S;R[%eax] = R[%edx]:R[%eax] / S;有符号除法,保存余数和商divl SR[%edx] = R[%edx]:R[%eax] % S;R[%eax] = R[%edx]:R[%eax] / S;无符号除法,保存余数和商注:64位数通常存储为,高32位放在edx,低32位放在eax。条件码:条件码寄存器描述了最近的算数或逻辑操作的属性。CF:进位标志,最高位产生了进位,可用于检查无符号数溢出。OF:溢出标志,二进制补码溢出——正溢出或负溢出。ZF:零标志,结果为0。SF:符号标志,操作结果为负。比较指令:指令基于描述cmpb S2,S1S1 – S2比较字节,差关系testb S2,S1S1 & S2测试字节,与关系cmpw S2,S1S1 – S2比较字,差关系testw S2,S1S1 & S2测试字,与关系cmpl S2,S1S1 – S2比较双字,差关系testl S2,S1S1 & S2测试双字,与关系访问条件码指令:指令同义名效果设置条件sete DsetzD = ZF相等/零setne DsetnzD = ~ZF不等/非零sets DD = SF负数setns DD = ~SF非负数setg DsetnleD = ~(SF ^OF) & ZF大于(有符号>)setge DsetnlD = ~(SF ^OF)小于等于(有符号>=)setl DsetngeD = SF ^ OF小于(有符号<)setle DsetngD = (SF ^ OF) | ZF小于等于(有符号<=)seta DsetnbeD = ~CF & ~ZF超过(无符号>)setae DsetnbD = ~CF超过或等于(无符号>=)setb DsetnaeD = CF低于(无符号<)setbe DsetnaD = CF | ZF低于或等于(无符号<=)跳转指令:指令同义名跳转条件描述jmp   Label1直接跳转jmp   *Operand1间接跳转je     LabeljzZF等于/零jne    Labeljnz~ZF不等/非零js     LabelSF负数jnz    Label~SF非负数jg     Labeljnle~(SF^OF) & ~ZF大于(有符号>)jge    Labeljnl~(SF ^ OF)大于等于(有符号>=)jl     LabeljngeSF ^ OF小于(有符号<)jle     Labeljng(SF ^ OF) | ZF小于等于(有符号<=)ja     Labeljnbe~CF & ~ZF超过(无符号>)jae    Labeljnb~CF超过或等于(无符号>=)jb     LabeljnaeCF低于(无符号<)jbe    LabeljnaCF | ZF低于或等于(无符号<=)转移控制指令:(函数调用):指令描述call    Label过程调用,返回地址入栈,跳转到调用过程起始处,返回地址是call后面那条指令的地址call    *Operandleave为返回准备好栈,为ret准备好栈,主要是弹出函数内的栈使用及%ebp

  • weesetup 微型grub安装工具 V1.3

    wee 是一个微型的grub4dos用于安装到硬盘mbr上,可以用来代替之前的grldr.mbr方案。 支持的文件系统: FAT12/16/32/NTFS EXT2/3/4 weesetup是为了方便安装wee63.mbr而写的程序。支持自定义脚本。

  • [原创] 大小写转换函数简化版

    在编程中经常会需要对字符串进行大小写的转换。 正常情况下是用两个函数upper和lower进行转换。 其实转换的方法还是有挺多种的 比如我之前写的:C语言的基础函数大小写转换 今天再发一个合二为一的版本,一个函数可以就实现把字符串转换为大写或小写,而且代码也很简单:

  • 金山快盘PHP SDK(普通版+简化版)[2013-04-12]

    金山快盘开放平台 PHP SDK 来源: 时间: 2013-04-12使用方法: 有两个版本,一个是普通版kuaipan.class.php,一个是简化版(简化操作)kp.class.php 可以根据自己的需要选择使用。

  • [PHP] 简易的SMTP邮件发送类

    最近由于需要发送(带大附件)的邮件,上网找了一下,像PHPMailer等试了一下,虽然封装得很好,但是用起来都不太顺手。 像PHPMailer发送大附件时就会提示类似如下的错误: Allowed memory size of 16777216 bytes exhausted (tried to allocate 7355049 bytes)

  • 使用PHP+CURL搭建一个简易的HTTP代理服务端[2012-12-17]

    使用PHP做的一个简易HTTP代理服务端,没有多少技术含量.有时可以利用一下.嘿嘿.比如在公司内部可以用它来偷偷上网,当然了要求了内部网站,并且支持PHP而且该服务器可以上网,你还要有办法访问到这个电脑.

  • PHP相关记录

    PHP Curl 417 Expectation Failed原因: 服务端使用lighttpd,而lighttp不支持返回”Expect: 100-continue”这样的header,就会以417 “Expectation failed” 来代替(lighttpd 1.5.0无此问题)。解决方法:更新到新版或设置CURL头信息CURLOPT_HTTPHEADER=>array(‘Expect:’);

  • [原创] 电信天翼云盘直链效果测试

    最近在学习PHP,随手做几个基于网盘的直链,,嘿嘿以后不用担心没有地方放文件了. 初步测试,挺稳定的说,放一段时间看一下. 没有什么好说的.直接上效果, 图片直链 MP3在线播放 你的浏览器不给力呀,要支持html5的才行喔。建议试试chrome。

  • [分享] 使用 PHP CURL 模拟登录新浪微博

    有时候我们获取一些新浪微博的数据,但又不想使用API,只好使用模拟登录了. 发现以前可以使用的CURL模拟登录代码失效了,Google一下,发现有很多人碰到这个问题.但是没有找到解决方法,所以就自己研究了一下,发现了原因.

  • [分享] 华为网盘的直链测试(免费版)

    最近学习了一下PHP,这个其实比金山快盘的直链更早写的, 相比官方的版本,更简单,这个没有限制目录的哦,不需要流量费的,可能会被封锁,不过这个是利用官方提供的API写的,应该不会,关键是华为网盘的速度够快.若是被封锁了就有些可惜.

  • 金山快盘直链

    使用快盘API写了一个直链的应用测试.. 以后可以把文件或图片直接上传到快盘中,然后直链. API有调用限制,好像是一天5000次,对于我等小站来说足够用了, 另外好像快盘的文件下载速度没有华为网盘的给力啊.速度相对比较慢,可以对比一下我的另一个文章关于华为网盘直链的测试,显示图片的速度更快.

  • 网盘外链的简单破解

    目前国内有许多网盘,大都是禁止外链的,即使支持也需要钱的. 一般网盘的下载链接只能从网盘所属域上链接下载,或直接输入地址下载.如果你把这个链接放到你的网站上是不可以用的. 像这种一般情况下是根据来源地址(Referer)判断的,如果来源地址是合法的域则可以下载,否则提示错误.

  • [原创]各类网站自动签到/带源码[2012-10-10更新]

    鉴于目前的许多网络硬盘,一般初始空间比较小,要获取更多免费的空间除了邀请好友加入以外,就是签到功能了,目前国内的网盘都有类似的功能。 一些人可能同时拥有N个网盘,每天打开然后签到,有点浪费时间,但是为了这一些免费空间还是会有人乐此不疲的。

  • [分享] 自己动手,在WINDOWS系统中搭建GRUB4DOS编译环境[2014-06-25]

    因为经常使用WINDOWS系统,为了方便直接在WINDOWS下搭建。 使用Colinux可以很方便的在WINDOWS中运行一直真实的Linux环境。 好了,废话不多说了,直接开始了。如果想偷懒的话,有提供了可以直接使用的成品下载。

  • [分享] LuaJIT的FFI调用WINDOWS API功能示例

    使用LuaJIT的FFI调用WINDOWS API来实现一些特别功能。比如网络访问,修改窗体,获取鼠标下的文本,获取鼠标位置等。

  • [转] Lua简明教程

    Lua脚本是一个很轻量级的脚本,也是号称性能最高的脚本,用在很多需要性能的地方,比如:游戏脚本,nginx,wireshark的脚本。这只是一篇非常简单的语言学习文章,希望能让你在入厕或是上班公车途中一口气很流畅地读完,从而对Lua这个脚本语言有一个比较大致的了解。

  • [PHP] 中文转拼音首字母简易实现方案

    在某些情况下,为了简化查询,我们需要提取中文的拼音首字母, 比如”中华人民共和国” 是ZHRMGHG 最近在ALMRun程序就用到了这个方法,,顺便写了一下PHP版的.感觉PHP的更简单哈, 适用于要求不是很高的场合,因为这个没有处理多音字,只支持GB2312字符,不过优点就是足够简单,几行代码的问题.有需要的可以拿去用,欢迎报错.

  • [分享] ALMRun–小巧的快速启动工具

    ALMRun 是一个实用绿色的快速启动软件,类似于ALTRUN等同类软件,集成了ALTRUN的优点.绿色实用,支持管理热键/程序,支持模拟输入,支持LUA扩展,通过LUA扩展.无所不能.

  • [学习] LUA脚本学习1

    获取WINDOWS文件的文件名/路径/扩展名例子: WINDOWS下环境变量扩展 例子: 获取CMD命令输出结果 例子: 其中read参数可以如下 *a 读取所有内容 *n 读取为数据(当输出为数字时用,否则会得到空值)

  • [PHP] 打算整合多个网盘资源

    目前有N多的网络硬盘,各有各的好处和优缺点.另外基本上都有开放API.只是API调用方法都不一样.若是可以让所有网盘的调用方法变得一致.这样一来如是要开发什么的都很方便了.一个网盘不行了就换一个,什么代码都不用改.

  • Cameyo PackageEditor 简体中文版(增强版)

    Cameyo 是一款完全免费的应用程序虚拟化 (Application Virtualization) 工具或者说单文件软件制作工具,PackageEditor 是 Cameyo 的虚拟化程序包修改编辑器,这是基于原版进行细微修改的简体中文版.

  • Hexo 模块化主题

    hexo模块化主题,自由,强大,本主题还通过主题插件实现了很多特色功能(仅此一家).支持多个一级分类、子分类、iLink文章内链、ijs文章内嵌脚本等.

  • [原创] pretty自动加载语言代码

    使用jquery代码实现 pretty 根据需要自动加载对应语言的.不受路径/CDN限制,自动获取prettify文件的路径,自动加载需要的代码高亮文件.