Yan's profilecomputing lifePhotosBlogListsMore ![]() | Help |
|
|
[coding]DirectShow的配置问题[coding]DirectShow的配置问题
注:本文主要内容改编自互联网。感谢这些内容的原创者、Linxie以及Tao。 我的妈搞死我了。总结一下造福后来人。 首先,现在版本的DirectX并不包括DirectShow,如果光辛辛苦苦下了一个200MB+的DirectX SDK,然后郁闷地google为什么用不了DirectShow,请再去下一个4MB的DirectShow SDK先。 要使用DirectShow的大部分功能,需要编译它的一个sample(诡异啊诡异),位置在\Samples\C++\DirectShow\ 这里就有一个叫baseclasses的工程,为安全起见,请先备份此工程。 1. 双击baseclasses.sln打开,按提示转换工程,编译。 提示错误: 1>D:\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(222) : error C2146: syntax error : missing ';' before identifier 'PVOID64' 1>D:\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(222) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>D:\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(5940) : error C2146: syntax error : missing ';' before identifier 'Buffer' 1>D:\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(5940) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>D:\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(5940) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>d:\DX90SDK\Samples\C++\DirectShow\BaseClasses\ctlutil.h(278) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 第一类问题的解决:错误发生在:operator=(LONG);函数定义中,这是因为在VC6中,如果没有显示的指定返回值类型,编译器将其视为默认整形;但是vs2005不支持默认整形,解决这个问题不能修改每个没有显示指示返回值类型的函数地方,可以用wd4430来解决;具体的在工程选项中的c+ +/Command Line中添加/wd4430即可。 2. 在Tools->Options->Projects and solutions->vc++ directories->show directories for里选择include files 然后增加 DX90SDK\Include DX90SDK\Samples\C++\DirectShow\BaseClasses DX90SDK\Samples\C++\Common 可能会问题依旧,调整一下include files的顺序,把它们都放在最后。 然后在project->BaseClasses properties->configuration->C/C++ -> General->Additional Include Directories里面的内容(.,..\..\..\..\include)删掉,重新编译 ,PVOID64的错误消失,原因如下: POINTER_64 是一个宏,在64位编译下起作用,它包含在SDK目录下的BASETSD.H中(Microsoft Visual Studio 8\VC\PlatformSDK\Include\basetsd.h(23):#define POINTER_64 __ptr64),但DXSDK自己也带了一个basetsd.h,里面没有定义POINTER_64,从而导致出错,只需要改变include files的优先级即可。当然,也可以改写winnt.h中的代码,在下面这两行: typedef void *PVOID; typedef void *POINTER_64 PVOID64; 之前增加一行: #define POINTER_64 __ptr64 3. 到目前为止,还剩下: BaseClasses\ctlutil.h(278) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 这个错误,解决方法如下: 打开project->BaseClasses properties->configuration->C/C++ ->Command Line,增加/wd4430选项。 4. 接着编译,提示error C2065: 'Count' : undeclared identifier等等错误,这个是微软的历史遗留问题了,C++标准语法的问题,因为在之前在for循环内定义的变量可以在for之外的地方使用,即 在第一个for里for(int i,...),以后的for再使用i不必再声明,解决方法也很简单,打开project->BaseClasses properties->configuration- >C/C++->Language->Force Comformance in For Loop Scrope设置为No即可。当然,也可以手动改代码,增加一个声明就是了。 经过上面几个步骤,应该是可以顺利编译了,对于其它版本的工程,照样设置就可以了,总共编译出下面4个文件备用: BaseClasses\Debug\strmbasd.lib BaseClasses\Debug_Unicode\strmbasd.lib BaseClasses\Release\STRMBASE.lib BaseClasses\Release_Unicode\STRMBASE.lib 在lib里面加入 commctrl.lib coredll.lib strmiids.lib strmbase.lib uuid.lib ole32.lib commdlg.lib 你或许需要在Tools->Options->Projects and solutions->vc++ directories->show directories for->library files里把它们加进去。 赶快编译DX90SDK\Samples\C++\DirectShow\Players\PlayDMO工程试试看吧。 [coding][zz]大话“20 世纪10大算法”大话“20 世纪10大算法” 本文基于下列材料编写: [Coding]GPopup[Coding]GPopup 此外,stephen同学从跨平台兼容性的角度提出了很好的建议。可是我所知道的跨平台的方法就是在每个平台下都写一份代码,然而目前主流的操作系统Windows和Linux在创建线程/进程、界面构造等方面差异实在太大,除了傻傻的把这个程序再写一遍,我个人实在不晓得怎么搞 :-( 然后stephen同学说到了标准的问题,只要在写代码的时候支持POSIX标准就好了~另外,他提到了Linux和Windows在设计理念上的不同。觉得很好,引用如下:(已征得作者允许) [coding]补码的设计思路[coding]补码的设计思路 P.S.探讨既知知识的发明历程是一件很有意思的事情~假装他们还没有被发现,照着一般的思路来思考~发现~发明~~~ [coding]请喊我代码民工头,谢谢[coding]请喊我代码民工头,谢谢 P.S.以后除了注意算法以外,在写代码之前更要注意它的意义和整个程序中的地位。也许写代码之前先写用户文档是个不错的主意。 [coding]template的头文件问题[coding]template的头文件问题 写一个模板类的时候,照往常一样将声明和定义分开存放。然后在main前#include相应的头文件。可是连接的时候就是过不了,非要把.cpp文件也#include了才可以。 比较诡异的一点是,在用Visual Assist X的Create implementation功能时,平常都是在.cpp文件中自动创建定义,可是在这个模板类里,它把定义自动放在了头文件里。 后来通过上课听讲和查询资料才知道,模板类的定义和一般类是不一样的,在模板函数“定义”的时候并不立刻生成代码,分配内存,而是在调用的时候根据相应的类型参数分配代码段内存。从这个角度出发,模板函数的定义也应归为头文件中。 上课听讲还是很重要滴~同时感谢Stephen同学的热心帮助~~~ [coding]源码面前 了无秘密[coding]源码面前 了无秘密
前两天每天熬夜两三点牛逼哄哄把2D-World和WumpusWorld的平台写出来了。方格世界周游世界的Agent写的无比复杂,当时还一览众山小的大放厥词,说只要是简单的算法都是错的。 妈的人太狂就是要遭雷劈的啊。 Stephen的算法写出来了,核心代码27行。这还是他良好的风格下无数空行和单独占行的大括号造就的。无语了都。 他的平台功能更强,更人性化,支持多Agent,算法试了几张地图没发现什么错。连平台带Agent才16K,想想我23K的庞然大物,汗颜啊。 总结了一下原因,一个是他的算法的确比我原先的算法好,和道福的算法是一样的,这个问题在前面的文章里已经分析过;另一个原因就是他编码的精巧和简洁。 当然,我没有说编码短就是好,但精巧简洁和短是两码事。 最重要的一点是,数学帮助他简化了很多很多的编码。 在我的代码里,转弯是一个复杂的switch: //Rotate Right switch (LastDirection.to_ulong()) { case UP: ActionResult = RIGHT; break; case DOWN: ActionResult = LEFT; break; case LEFT: ActionResult = UP; break; case RIGHT: ActionResult = DOWN; break; } 但Stephen的就要简单许多: void turnRight(){dir = (dir+2) % 8;} 都是用bitset放数据,数据结构都是一样的,算法我为什么就想不到呢?想了一下,觉得可以从以下几个方面来解释。 首先是对代码要有优化意识。最直观的算法往往是很笨的。每次想到一种解决方法,尤其是看起来比较复杂的解决方法后,都要想一想,这个算法可以优化吗?不要想出来一个SB算法立马就跟代码民工似的吭哧吭哧写的一表多开心。 然后是对经常出现的代码尤其要有优化意识。这个是优化的重点,在写完了以后还是要看一下的。 最后要有利用数学进行抽象,简化编码的意识。数学的力量在于它的抽象性和概括性。既然我的数学不怎么熟练,不能做到一开始就想出那么艺术性的算法,就需要在提出算法以后有意识地想一想,这个复杂的算法可以用数学来抽象吗?常此以往,设计算法能力应当会有质的提高。 提出要有这些意识是一回事,平时注意养成习惯又是一回事了~我会努力的~sigh~算法,我还差得远呢~一天到晚装B,被雷劈了才晓得自己是SB~ Stephen编码简洁的第二个原因是类写的不像我那么啰嗦。看看我写的代码里很多都是废代码,那些类接口写的,明知道永远用不到还写一身劲,以后要改。 把道福和Stephen放一起总结一下。总的来说就是三思而后行,还有看本质,用数学的习惯要在平时培养。嘿,其实做人不也这样? 感谢上帝,感谢Stephen,在我狂的时候劈了我一下。被劈的外焦里嫩的-_-b|||,以后一定夹着尾巴做人,专心做一SB小言言~ P.S. 其实Stephen的算法和道福一致,只是实现的更“相对化”,绝对坐标体现的更弱。这一点导致了编码的简洁。
附:我根据Stephen思路修改的代码(原来花了我一晚上时间,写了6K啊……) /* program: World2DAgent.cpp function: the implementing file of the agent travelling around the virtual 2D-world. author: grapeot date: 20080909 last modified date: 20080910 */ #ifndef _INC_WORLD2DAGENT_CPP
#define _INC_WORLD2DAGENT_CPP #include "World2DAgent.h"
//travel around the virtual world counter-clockwise
bitset<8> World2DAgent::Action(bitset<8> SensorState) { bool isRightWall = !SensorState[(Direction + _R - _U) % 8]; bool isLeftWall = !SensorState[(Direction + _L - _U) % 8]; bool isFrontWall = !SensorState[Direction]; bool isFrontRightWall = !SensorState[(Direction + _RU - _U) % 8]; bool isFrontLeftWall = !SensorState[(Direction + _LU - _U) % 8]; bool isBacktRightWall = !SensorState[(Direction + _RD - _U) % 8]; bool isBackLeftWall = !SensorState[(Direction + _LD - _U) % 8]; if (isRightWall) { if (!isFrontWall) ; //go forward else if (!isLeftWall) Direction = (Direction - 2) % 8; //turn left else Direction = (Direction - 4) % 8; //turn back } else { if (isBacktRightWall) Direction = (Direction + 2) % 8; //turn right else if (isBackLeftWall) Direction = (Direction - 4) % 8; //turn back else if (isFrontLeftWall) Direction = (Direction - 2) % 8; //turn left else if (isFrontRightWall) ; //go forward else if (!isFrontWall) ; //go forward else if (!isLeftWall) Direction = (Direction - 2) % 8; //turn left else Direction = (Direction - 4) % 8; //turn back } return bitset<8>(0).set(Direction);
} #endif [coding]学到一个新词 剧透!慎入!WumpusWorldSimulationPlatformDemo 标题要长长长长长Starting to read the world from input file: ExampleWorld.txt m reads successful, m = 5 n reads successful, n = 4 World content reads successful. Content: WP... ..... GP... ..P.. Step 0 --------------------------------- WP... ..... GP... X.P.. --------------------------------- Agent location: (0, 3)Agent direction: Right AgentSensorState: AgentLastAction: TakenGold: 0 Shoot: 1 Score: 0 Step 1 --------------------------------- WP... ..... GP... X.P.. --------------------------------- Agent location: (0, 3)Agent direction: Up AgentSensorState: AgentLastAction: TurnLeft TakenGold: 0 Shoot: 1 Score: -1 Step 2 --------------------------------- WP... ..... XP... ..P.. --------------------------------- Agent location: (0, 2)Agent direction: Up AgentSensorState: Breeze Glitter AgentLastAction: Go TakenGold: 0 Shoot: 1 Score: -2 Step 3 --------------------------------- WP... ..... XP... ..P.. --------------------------------- Agent location: (0, 2)Agent direction: Up AgentSensorState: Breeze AgentLastAction: Grab TakenGold: 1 Shoot: 1 Score: -3 Step 4 --------------------------------- .P... ..... XP... ..P.. --------------------------------- Agent location: (0, 2)Agent direction: Up AgentSensorState: Breeze Scream AgentLastAction: Shoot TakenGold: 1 Shoot: 0 Score: -4 The agent sends a CLIMB instruction. But it is not in the start, instruction ign ored. Step 5 --------------------------------- .P... ..... XP... ..P.. --------------------------------- Agent location: (0, 2)Agent direction: Up AgentSensorState: Breeze AgentLastAction: Climb TakenGold: 1 Shoot: 0 Score: -5 Step 6 --------------------------------- .P... ..... XP... ..P.. --------------------------------- Agent location: (0, 2)Agent direction: Right AgentSensorState: Breeze AgentLastAction: TurnRight TakenGold: 1 Shoot: 0 Score: -6 Step 7 --------------------------------- .P... ..... XP... ..P.. --------------------------------- Agent location: (0, 2)Agent direction: Down AgentSensorState: Breeze AgentLastAction: TurnRight TakenGold: 1 Shoot: 0 Score: -7 Step 8 --------------------------------- .P... ..... .P... X.P.. --------------------------------- Agent location: (0, 3)Agent direction: Down AgentSensorState: AgentLastAction: Go TakenGold: 1 Shoot: 0 Score: -8 Step 9 --------------------------------- ...P. ...P. .G.P. XP..W --------------------------------- Agent location: (0, 3)Agent direction: Right AgentSensorState: Breeze AgentLastAction: Climb TakenGold: 0 Shoot: 1 Score: 991 The agent sends a STOP instruction. 请按任意键继续. . . [coding][神!][原创]手把手教你用机器码编程[coding][神!][原创]手把手教你用机器码编程
本文的目的在于让各位了解最基本的机器码知识。 例程仅有30字节,尽情揭露各位的本质~咔咔~ 方法1: 1.开始->运行,输入debug,回车 2.复制如下代码并粘贴到debug中去: e100 BA 11 01 B4 09 B9 0A 00 CD 21 E2 FC B4 01 CD 21 e110 C3 49 20 61 6D 20 61 20 53 42 2E 0D 0A 24 具体的方法是单击debug窗口左上角的命令提示符图标,选择编辑->粘贴,回车即可。 3.输入g (运行的意思,括号里面的东西不要傻乎乎打进去啊),回车,看结果吧~ 4.看完结果后按q回车可退出debug。 方法2: 1.打开UltraEdit32,新建一个文件,输入30个A(或者随便什么字符,仅为下一步做准备)。 2.按Ctrl + H切换到HEX编辑模式,定位到第一字节,依次输入下列代码: BA 11 01 B4 09 B9 0A 00 CD 21 E2 FC B4 01 CD 21 C3 49 20 61 6D 20 61 20 53 42 2E 0D 0A 24 3.保存为.com文件,双击运行看看! 代码分析:
方法1里,e100,e101是debug的内部命令,暂且不管,其他部分是指令。 为了方便分析,首先将地址和代码对应一下: 00h: BA 11 01 03h: B4 09 05h: B9 0A 00 08h CD 21 0Ah: E2 FC 0Ch: B4 01 0Eh: CD 21 10h: C3 11h: 49 20 61 6D 20 61 20 53 42 2E 0D 0A 24 从11h开始实际是I am a SB, CR, LF(回车换行), $的ASCII码,注意偏移地址为11h。这是这个程序的数据段。下面分析指令段。 回忆一下计算机文化基础的内容,CPU的指令由操作符和操作数组成,前面已经将每条指令都划分出来了。第一个字节是操作符,后面的是操作数。 再普及一个知识,.com文件读入内存时前100h字节是保留的,因此在内存寻址时需要把偏移量加上100h成为绝对地址。知道了这些就可以分析这个程序了。 频繁出现的一个指令是CD 21,CD的意思是调用DOS中断,那这个21(注意是16进制)是不是很熟悉啊~~它就是操作数~CD 21就是调用21号DOS中断的意思~如果不晓得什么是DOS中断的话,只要知道B4 09, BA指令和CD 21结合可以显示一个字符串,B4 01和CD 21结合可以读入键盘就可以了~ 前2条指令,B4 09让电脑准备打印字符串,(在CD 21时正式开打),BA 11 01将字符串的地址11 01读入寄存器,由于x86架构采用高地址存高位的存储方式,所以这里实际上把I am a SB的绝对首地址0111h读入了寄存器,经过了这两步之后,只要调用CD 21,就可以打印字符串了~ 05h: B9 0A 00和0Ah: E2 FC构成了一个循环。B9指令将循环次数0A 00(即10次)读入循环寄存器,E2是循环跳转指令,将循环寄存器内的值减一,如果寄存器内的数不是0则跳转到相应偏移量的地方去执行,否则继续下一条指令。这里偏移量是FC,即-4,所以向前跳4个字节,即08h的地方执行。 若10次打印结束,调用B4 01, CD 21,暂时中断程序,等待从键盘读入一个字符,这里实际上起得是一个Press any key to continue的作用。 C3是退出程序的指令。 所以整个程序的作用就是,打印一个字符串10次,然后中断程序,在用户按下任意键后退出。 事实上也很容易发现,机器码和汇编有很简单的一一对应的关系(至少这个程序里是这样),所以很容易反汇编出它的汇编源程序(执行完方法1后,直接键入u回车即可反汇编): 147A:0100 BA1101 MOV DX,0111 147A:0103 B409 MOV AH,09 147A:0105 B90A00 MOV CX,000A 147A:0108 CD21 INT 21 147A:010A E2FC LOOP 0108 147A:010C B401 MOV AH,01 147A:010E CD21 INT 21 147A:0110 C3 RET ;此处开始为数据段,但反汇编器没我们聪明看不出来,依旧照指令的方式反汇编 147A:0111 49 DEC CX 147A:0112 20616D AND [BX+DI+6D],AH 147A:0115 206120 AND [BX+DI+20],AH 147A:0118 53 PUSH BX 147A:0119 42 INC DX 147A:011A 2E CS: 147A:011B 0D0A24 OR AX,240A 147A:011E 0000 ADD [BX+SI],AL 人工修饰一下得到:
ORG 100h ;伪指令,com文件必须 MOV DX, OFFSET msg
MOV AH, 9 MOV CX, 10 next: INT 21h LOOP next MOV AH, 1
INT 21h RET
msg DB 'I am a SB.', 0dh, 0ah, '$'
你也可以试试改动机器码~写出自己用原汁原味的机器码写出的HelloWorld!
P.S.如果没有UltraEdit也可以用C写一个小程序如下:
#include<stdio.h> int main(void) { char data[30] = {0xBA, 0x11, 0x01, 0xB4, 0x09, 0xB9, 0x0A, 0x00, 0xCD, 0x21, 0xE2, 0xFC, 0xB4, 0x01, 0xCD, 0x21, 0xC3, 0x49, 0x20, 0x61, 0x6D, 0x20, 0x61, 0x20, 0x53, 0x42, 0x2E, 0x0D, 0x0A, 0x24}; FILE *F = NULL; F = fopen("temp.com", "wb"); fwrite(data, 1, 30, F); fclose(F); return 0; } 值得玩味的是,fopen的模式改成w就不行,wb就可以。经过比较两个模式下生成的文件发现,在wb模式下,文件与data数组的内容完全相同,但是在w模式下,data中所有单独出现的0A或者0D都被篡改成了0A 0D(回车换行),这样就可以理解为什么w被定义为适用于文本文件的输出格式了。所有单独的回车符或者换行符都被当作回车换行符输出来。这样对Windows环境下的文本文件而言的确不容易出乱子。 [coding]汇编风格[coding]汇编风格
TEST, CMP等等要和条件跳转语句紧挨着,否则中间的其他语句可能会破坏PSW。 选择寄存器很重要,要了解在何种情况下这个寄存器的值会改变。比如调用21H中断会改变AL寄存器的值(即使AH != 1的情况下有时也如此)。所以就在调用中断前确认参数是好习惯。 AX寄存器不能用来间接寻址, DX不可用来段间寻址? 段定义中的名字代表的是地址。 用存储单元传递参数思路比较清晰,但不适用于递归。 用堆栈传递参数时不要忘了加上段前缀SS: P.S.汇编这么麻烦,不如自己写个编译器算了
P.S.2. 所谓细心不出错就是这样积累来的。 P.S.3.历时5天的汇编学习至此告一段落。 [coding][实用]阶乘[coding][实用]阶乘
这样简单的代码贴上来的确比较丢人,但是有不少实用的地方,比如子程序的调用,堆栈传参数,递归的写法,2进制向BCD码的转换(不要用除法,效率太低下)等等。 汇编不是用来做数学运算的,做接口才是王道。 ;program: factor.asm
;function: calculate factor using recursion ;author: grapeot ;date: 20080811 name 'factor'
.model small
.stack 100h .data MsgEnter DB 0dh, 0ah, '$' Msg1 DB 'Please input a number(0~8):$' Msg2 DB 'Factor of the input:$' Msg3 DB 'Error! Input out of range!', 0dh, 0ah, '$' Word2BCD_DecimalBase: DW 1, 10, 100, 1000, 10000 .code main PROC far .startup ;input begin: LEA DX, Msg1 MOV AH, 9 INT 21h MOV AH, 1 INT 21h MOV BL, AL ;store the input AND BL, 0fh ;adjust for ascii code LEA DX, MsgEnter MOV AH, 9 INT 21h ;enter ;check the input CMP BL, 8 JA err JMP nerr err: CALL error JMP begin nerr: ;output header LEA DX, Msg2 MOV AH, 9 INT 21h ;call the subproc MOV BH, 0 PUSH BX ;to from a word and then deliver the parameter CALL fact CALL Word2BCD .exit 0 RET main ENDP ;fact proc near
;calculate the factor of the input using recursion ;the parameters and result are delivered via stack fact PROC near ;preserve the original registers PUSH AX PUSH BX PUSH DX ;calculate MOV BX, SP MOV AX, SS: BX[8] CMP AX, 0 JNE next ;MOV BX, SP MOV SS: BX[8], 1 JMP FactReturn next: ;next recursion MOV DX, AX DEC DX PUSH DX CALL fact POP DX MUL DX ;MOV BX, SP MOV SS: BX[8], AX ;restore the original registers and push the result FactReturn: POP DX POP BX POP AX RET fact ENDP ;error proc near
;prompt an error message ;no parameters are passed error PROC near PUSH DX PUSH AX LEA DX, Msg3 MOV AH, 9 INT 21h POP AX POP DX RET error ENDP ;Word2BCD proc near ;convert a word of binary code into BCD code then print it on the screen ;the parameters are delivered via stack Word2BCD PROC near ;preserve original contents in registers ;and get the parameter PUSH AX PUSH BX PUSH CX PUSH DX MOV BX, SP MOV AX, SS: BX[10] ;deal with the first 4 figures MOV CX, 4 Word2BCD_Next: MOV BX, CX ADD BX, CX MOV BX, DS: [Word2BCD_DecimalBase + BX] MOV DX, 0 ;use subtraction to do division for 10000 is too large for a single byte Word2BCD_Compare: CMP AX, BX JAE Word2BCD_Subtract JMP Word2BCD_Continue Word2BCD_Subtract: INC DX SUB AX, BX JMP Word2BCD_Compare Word2BCD_Continue: CMP DL, 0 JE Word2BCD_Loop MOV BX, AX ;store the remain in BX for AX will be used for calling interpretation OR DL, 30h MOV AH, 2 INT 21h MOV AX, BX ;restore AX Word2BCD_Loop: LOOP Word2BCD_Next ;deal with the digit MOV DL, BL OR DL, 30h MOV AH, 2 INT 21h POP DX POP CX POP BX POP AX RET 1 Word2BCD ENDP [coding]second assemble program[coding]second assemble program
第一个理所当然是HelloWorld,第二个是个查找表,查找0~9的平方,用二进制和十进制打印出来。 SourceCode: ;Program: search.asm
;Function: do a search operation then print the result on the screen in binary and decimal ;Author: grapeot ;Date: 20080811 name 'Search'
.model small
.stack 100H .data table DB 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 msg1 DB 'Please input one number (0~9):$' msg2 DB 'Square of input:', 0dh, 0ah, '$' result DB 2 dup (0) DB 'd$' MsgEnter DB 0dh, 0ah, '$' .code .startup PSearch PROC far input: LEA DX, msg1 MOV AH, 9 INT 21h MOV AH, 1 INT 21h AND AL, 0fh MOV AH, 0 ;adjust for ascii code search: LEA BX, table ADD BX, AX MOV BL, BYTE PTR [BX] LEA DX, MsgEnter MOV AH, 9 INT 21h LEA DX, msg2 MOV AH,9 INT 21h MOV CX, 8 ;8 bits printb: TEST BL, 10000000b JZ mov0 mov1: MOV DL, '1' JMP callint mov0: MOV DL, '0' callint: MOV AH, 2 INT 21h ROL BL, 1 ;use ROtateLeft instead of SHiftLeft to preserve the result after print LOOP printb MOV DL, 'b' MOV AH,2 INT 21h LEA DX, MsgEnter MOV AH, 9 INT 21h MOV AX, 0 convertd: ;convert to decimal CMP BL, 0ah JAE continue ; end MOV AL, BL OR AL, 30h OR AH, 30h ;adjust for ascii code MOV [result], AH ;tens MOV [result + 1], AL ;digit JMP printd; continue: INC AH SUB BL, 0ah JMP convertd printd: LEA DX, result MOV AH, 9 INT 21h PSearch ENDP .exit 0 END [coding]好花哨的HelloWorld...zz from the first example of emu8086
name "hi-world"
; this example prints out "hello world!"
; by writing directly to video memory. ; in vga memory: first byte is ascii character, byte that follows is character attribute. ; if you change the second byte, you can change the color of ; the character even after it is printed. ; character attribute is 8 bit value, ; high 4 bits set background color and low 4 bits set foreground color. ; hex bin color
; ; 0 0000 black ; 1 0001 blue ; 2 0010 green ; 3 0011 cyan ; 4 0100 red ; 5 0101 magenta ; 6 0110 brown ; 7 0111 light gray ; 8 1000 dark gray ; 9 1001 light blue ; a 1010 light green ; b 1011 light cyan ; c 1100 light red ; d 1101 light magenta ; e 1110 yellow ; f 1111 white ORG 100h ; set video mode
MOV AX, 3 ; text mode 80x25, 16 colors, 8 pages (ah=0, al=3) INT 10h ; do it! ; cancel blinking and enable all 16 colors:
MOV AX, 1003h MOV BX, 0 INT 10h ; set segment register: MOV AX, 0b800h MOV DS, AX ; print "hello world"
; first byte is ascii code, second byte is color code. MOV [02h], 'H'
MOV [04h], 'e'
MOV [06h], 'l'
MOV [08h], 'l'
MOV [0ah], 'o'
MOV [0ch], ','
MOV [0eh], 'W'
MOV [10h], 'o' MOV [12h], 'r'
MOV [14h], 'l'
MOV [16h], 'd'
MOV [18h], '!'
; color all characters: MOV CX, 12 ; number of characters. MOV DI, 03h ; start from byte after 'h' c: MOV [DI], 11101100b ; light red(1100) on yellow(1110)
ADD DI, 2 ; skip over next ascii code in vga memory. LOOP c ; wait for any key press:
MOV AH, 0 INT 16h RET
运行结果:
[coding]天哪天哪天哪[coding]天哪天哪天哪
EditPlus就是神啊,AoGo神啊~ 以前只知道EditPlus+gcc组简单的C/C++ IDE,原来结合Windows批处理/脚本还是可以这样玩的啊~ 给MASM For EditPlus做下广告吧~ Windows也可以组IDE的啊,不逊于VI + gcc + gdb哦~而且EditPlus不比那个号称巨无敌,但学习至少要3个月的VI差哦~只是大家不知道怎么用而已~比如选定一个矩形区域(在未Word Wrap的模式下Alt + 鼠标拖动),比如一次删除一个词(Ctrl + Backspace),都很方便,而且快捷键比VI的诡异容易适应很多。而且他的可扩展性也很无敌~哼哼~ 把MASM for EditPlus的Readme贴上来~
===================================================== MASM For EditPlus v1.0 Serial 0002自述文档 =========================================================== !!!如果您是第一次安装MASM for EditPlus 1.0,我强烈建议您认真的看完这个ReadMe文件!!!
EditPlus注册信息:
================================= 用户:XXOXOXOXOX 注册码:XXOOXOXOX 关于前一版MASM for EditPlus v1.0 Serial 0001的说明
================================================== 经过长时间的修改与测试,MASM for EditPlus终于可以成为一个成熟的MASM配置包了,1.0的MASM for EditPlus即将完成之际,又得知MASM已经升级到v8.0,基于这个原因,我把MASM5、MASMv8.0的LIB/INCLUDE/BIN还有VC资源编辑专版一起打包到MASM for EditPlus中,方便大家(更多是为初学者)设置MASM开发环境,也就是说,我这样做的目的是只要您安装MASM for EditPlus就可以使用MASM进行Win32ASM编程,我决定把现在这个MASM for EditPlus正式定为1.0 Serial 0001,以便于日后大家对照版本号升级. MASMv8.0的升级变化非常大,在制作新的语法文件中,发现MASMv8.0相对于7.0升级方面做了非常大的更新,API函数新增6608个(包括UNIcode函数),新增247个结构类型,新增516个常数,包括以前不支持的一些控件风格现在都添加了,尤其在API函数方面,更新可说是巨大,添加了一些新的API模块,如MSI/SQL接口函数,其中有近1/3都是以前的函数的UNIcode函数,还优化了LIB,虽然编译器与链接器没有更新,但是MASM可以说是越来越完善,MASMv8.0更是为在Windows后述版本中开发程序打下良好的基础,我相信,只要没有停止更新,在Windows开发平台上,MASM将与通行世界的ANSI C一样是一个永恒的开发工具。
因为所以,这一次MASM for EditPlus的变化也非常大,批处理几乎全部重写,由原来的8个BAT集成在四个BAT中,更加小心地控制环境变量,尽量避免因为环境变量过多而发生"Out of environment space"的错误,相信控制之下此错误是不会再出现了(如果您不幸碰到这个错误而无法进行工作,请和我联系或到论坛提出),同时,MASM For EditPlus v1.0 Serial 0001集成了C/C++(VC6.0)的开发环境设置,能对C/C++进行很全面的支持,添加了新的C/C++模板,编辑C/C++文件现在能和MASM一样支持控制台与DLL的编译,支持语法检查,支持使用SoftICE进行源码级调试。
MASM for EditPlus v1.0 Serial 0002更新 ==================================================== 批处理在编译时会自动识别扩展名.asm/.c/.cpp进行不同的编译,MASM for EditPlus v1.0 Serial 0002最大的更新就是使用了一个程序进行编译时控制,EXE/DLL/LIB/VXD/MDI/DLG等等程序都只需要按Ctrl+1就可以编译,唯一的要求就是需要您在源程序的最前面添加一行来表示,只要在最前面三行就行,因为编译程序是在找到双引号后再取后面三个字符的,所以只需要关键字对就可以了,如在第一行直接提供;"EXE",当然C/C++则是//"EXE",相关的编译关键字有DOS/CON/DLG/EXE/MDI/DLL/VXD/LIB,这样做还有一个好外就是方便手工进行编译的朋友,你只需在启动时打通MASM的BIN目录,以后在DOS下只需要输入 mlink 文件路径 就可以一步编译完成.当然前提是程序中要提供编译说明. 出于可能发生错误,我没有提供当没有提供编译模式时的默认编译方式,如果您觉得有必要,可以这样做:打开BIN目录下的BuildASM.bat,找到"REM 默认方式跳转"一行,下面那行则是当没有提供编译关键字时的跳转,我默认是返回,如果您正在学习Win32汇编,可以选择跳转到ISEXE,如果正在学DOS汇编,则可以选择跳到ISDOS,这个就依你自己来看了。另外,BuildC++.bat也可以这样修改一下。 为了方便您定制MASM for EditPlus,编译程序的源代码也在BIN目录下,名字是compiler.c,如果您熟悉C/C++语言,您可以修改它来定制编译程序. 以下所有的说明都是Serial 0001 与Serial 0002相同的部分 ===================================================== 关于C/C++编译还有一个重要的信息就是,链接时我添加了基本的库文件,如果您在VC的源代码文件中用到了其它没有加入的库中的函数,则需要自己添加才行,具体请打开BIN目录下的BuildC++.bat,找到引用库的地方(就是kernel32.lib user32.lib gdi32.lib..这些列表),在其中添加其它没有引用的库文件名就行了.注意二个地方都要添加. 使用中快捷键有:(第一次编译请先保存)
----------------------------------------------------- CTRL+1 编译(.asm/.c/.cpp) CTRL+2 运行已经编译的程序 CTRL+3 使用SoftICE源码调试 CTRL+4 是进行资源编辑 工具位置与名字都可自定,另外还可以根据需要再增加新工具,如使用Debug调试DOS程序
关于相关模板的说明
=============================== 为了方便,我已经为您写了一系列的模板,对应表如下: ----------------------------------------------------- ASM-DOS DOS下汇编模板 ASM-CON 控制台程序模板 ASM-DLG 以对话框为主的程序模板 ASM-GUI 标准Windows32位GUI程序模板 ASM-MDI 标准Windows32位GUI多文档程序 ASM-DLL 动态库程序模板 ASM-VxD 虚拟设备驱动程序模板 ASM-LIB 函数库模板,把有用的函数编译为LIB可以方便地重利用 C++-CON 同上
C++-DLG 同上 C++-GUI 同上 C++-DLL 同上 C++-LIB 同上 -------------------------- 其中DLG/GUI/MDI/DLL等模板在编译时,如果同目录下不存在同名的RC/RES文件,则批处理会把对应的RES文件复制到当前源文件目录下面,DLL在检查RC/RES的同时,还会检查同目录下是否存在DEF文件,如果不存在则自动创建一个. 建议汇编初学者先从DOS汇编学起,再转向Windows GUI程序设计,而一些API函数的用法建议在C/C++中学习.
关于使用SoftICE进行源码级调试程序
=============================== 如果想使用SoftICE进行源码级调试程序,BIN目录下必须有MSPDB60.DLL这个文件,而这个文件在MASMv7.0的安装包中是没有带的,在VC6.0中倒是有一个,不过请放心,MASM For EditPlus安装时已经把这个文件安装到了BIN下. 您在编写程序时可以直接按CTRL+3或点工具栏上的3号工具进行带符号编译然后启动SoftICE进行源码调试,当然前提您得先安装好SoftICE并让它在系统启动时加载,1.0的MASM for EditPlus开始支持C/C++程序的源码级调试,如果您正确安装了SoftICE并已经加载,CTRL+3后会自动编译并激活SoftICE停在当前程序的入口处,调试时您可以在代码中设置断点,可都是源码级调试哟! 众所周知,用SoftICE进行源代码调试时不支持中文显示。
另外,请不要升级EditPlus,因为它高版本在文件扩展名上有些出入,升级后会因为这个原因而无法编译.
关于资源文件的使用 ================================ 您只需把资源脚本(rc)或资源模板(res)保存为与asm文件同名的文件即可,编译时编译包会自动识别,如果一个asm文件目录同时存在rc与res,默认为优先使用rc,这是因为很多的源代码都是使用rc,当然您可以修改.bat文件来改掉默认值,只需打开Bin目录下的BuildRES.bat,找到Set MAINRC=RC改成Set MAINRC=RES就行了. 建议使用VC资源编辑专版进行编辑并保存为RES.因为VC资源编辑版保存为RC后会因为一些设置而导致无法编译成OBJ. 如果您不会写批处理,请不要修改.bat文件,如果想重新设置参数,可以重新安装一遍,在安装过程中把所有的路径都设置好,另如果由于其它任何原因导致无法正常使用,也请重新安装,这样能恢复到最初状态。
使用中有任何问题,请给我发Mail或到我的论坛给发贴,我会尽力帮您解决.
MASM for EditPlus相对的优点:
============================ 1.支持关键字(汇编指令/API函数/API常数/API结构)语法高亮显示. 2.支持API函数/API常数/API结构自动完成(在输入后按空格会自动按正确单词改变大小写) 3.只需保存一次,以后保存、编译、链接、运行一步完成. 4.编译不同模式的代码时能自动的创建相关的文件 MASM for EditPlus已知的缺点:
============================ 1.新文件第一次编译必须手工保存 2.asm文件路径中不能包含空格. 3.不支持API函数/API常数/API结构原型显示(可以使用CGB的ApiPopList). 4.没有使用Make,每次编译都是全部更新. 估计下个版本的变化:
============================ 修改EditPlus,能让它有显示API函数原型的功能(有相当的难度,因为要反汇编EditPlus并插入自己的代码,如果实用性不高或本人难以适度此难度将放弃). 上述功能完成后,我想MASM for EditPlus基本上就不会再更新了,做为一个编辑器,这些功能已经能够很方便的进行编程,当然最主要的原因是EditPlus不是我写的程序,如果真的要做一个IDE,唯一的办法就是自己的,我也正在努力的写,希望能早日写出一个好的IDE。 本配置文件所有批处理与语法文件都是由AoGo自己编写配置的,花费了相当大的精力在其中,转载请不要去掉本文件。 ========================================
衷心希望MASM For EditPlus能给您一些帮助. ======================================== AoGo
sixnabs@163.com 站点域名: http://aogo.yeah.net [coding]VerilogHDL 比 VHDL优越的地方[coding]VerilogHDL 比 VHDL优越的地方
1. 符号{ }的使用 2. 位域选择 3. casex, casez的支持 4. 模块参数的设定 5. 编码更简洁,和C语言语法相近(这个是不是优越的地方就很难说了) 6.二维数组的应用更加方便 P.S.两天搞定VerilogHDL,感觉蛮好~进一步只能在实践中练习了~不过GRE荒废了…… P.S.2.海明码原来是(7,4)线性分组码啊 |
|
|