Profilo di 七夜Fly With The WindFotoBlogElenchi Strumenti Guida

Blog


29 aprile

CString与int、char*、char[100]之间的转换

CString互转int

将字符转换为整数,可以使用atoi、_atoi64或atol。
而将数字转换为CString变量,可以使用CString的Format函数。如
CString s;
int i = 64;
s.Format("%d", i)
Format函数的功能很强,值得你研究一下。

void CStrDlg::OnButton1()
{
// TODO: Add your control notification handler code here
CString
ss="1212.12";
int temp=atoi(ss);
CString aa;
aa.Format("%d",temp);
AfxMessageBox("var is " + aa);
}

sart.Format("%s",buf);

CString互转char*

///char * TO cstring
CString strtest;
char * charpoint;
charpoint="give string a value";
strtest=charpoint;


///cstring TO char *
charpoint=strtest.GetBuffer(strtest.GetLength());

标准C里没有string,char *==char []==string

可以用CString.Format("%s",char *)这个方法来将char *转成CString。要把CString转成char *,用操作符(LPCSTR)CString就可以了。


CString转换 char[100]

char a[100];
CString str("aaaaaa");
strncpy(a,(LPCTSTR)str,sizeof(a));
27 aprile

1030[Phone Home]编程总结

数据结构没想清楚,没有清晰的思路的时候就开始编.导致最后调了好长时间.
中间逻辑思维不严密,很多情况没考虑清楚,最后一点点的加很费事.
变量用过之后得恢复初试值,忘记了,出现了一处错误,查了半天才找到.
 
慢慢学习吧,努力中ing!(貌似很努力,哈哈)
11 marzo

const传奇

const传奇
xlander译 
--------------------------------------------------------------------------------
 
简介
当我自己写程序需要用到const的时候,或者是读别人的代码碰到const的时候,我常常会停下来想一会儿。许多程序员从来不用const,理由是即使没用const他们也这么过来了。本文仅对const的用法稍作探讨,希望能够对提高软件的源代码质量有所帮助。

常变量
变量用const修饰,其值不得被改变。任何改变此变量的代码都会产生编译错误。Const加在数据类型前后均可。
例如:
void main(void)
{
const int i = 10; //i,j都用作常变量
int const j = 20;
i = 15; //错误,常变量不能改变
j = 25; //错误,常变量不能改变
}

常指针
Const跟指针一起使用的时候有两种方法。

const可用来限制指针不可变。也就是说指针指向的内存地址不可变,但可以随意改变该地址指向的内存的内容。
int main(void)
{
int i = 10;
int *const j = &i; //常指针, 指向int型变量
(*j)++; //可以改变变量的内容
j++; //错误,不能改变常指针指向的内存地址
}

const也可用来限制指针指向的内存不可变,但指针指向的内存地址可变。
int main(void)
{
int i = 20;
const int *j = &i; //指针,指向int型常量
//也可以写成int const *j = &i;
j++; //指针指向的内存地址可变
(*j)++; //错误,不能改变内存内容
}
看完上面的两个例子,是不是糊涂了?告诉你一个诀窍,在第一个例子中,const用来修饰指针j,j不可变(也就是指向int变量的常指针);第二个例子中,const用来修饰*j,*j不可变(也就是指向int常量的指针)。

这两种方式可以组合起来使用,使指针和内存内容都不可变。
int main(void)
{
int i = 10;
const int *const j = &i; //指向int常量的常指针
j++; //错误,不能改变指针指向的地址
(*j)++; //错误,不能改变常量的值
}

Const和引用
引用实际上就是变量的别名,这里有几条规则:
声明变量时必须初始化
一经初始化,引用不能在指向其它变量。
任何对引用的改变都将改变原变量。
引用和变量本身指向同一内存地址。

下面的例子演示了以上的规则:
void main(void)
{
int i = 10; //i和j是int型变量
int j = 20;
int &r = i; //r 是变量i的引用
int &s; //错误,声明引用时必须初始化
i = 15; //i 和 r 都等于15
i++; //i 和 r都等于16
r = 18; //i 和r 都等于18
printf("Address of i=%u, Address of r=%u",&i,&r); //内存地址相同
r = j; //i 和 r都等于20,但r不是j的引用
r++; //i 和 r 都等于21, j 仍等于20
}

用const修饰引用,使应用不可修改,但这并不耽误引用反映任何对变量的修改。Const加在数据类型前后均可。
例如:
void main(void)
{
int i = 10;
int j = 100;
const int &r = i;
int const &s = j;
r = 20; //错,不能改变内容
s = 50; //错,不能改变内容
i = 15; // i和r 都等于15
j = 25; // j和s 都等于25
}

Const和成员函数
声明成员函数时,末尾加const修饰,表示在成员函数内不得改变该对象的任何数据。这种模式常被用来表示对象数据只读的访问模式。例如:
class MyClass
{
char *str ="Hello, World";
MyClass()
{
//void constructor
}

~MyClass()
{
//destructor
}

char ValueAt(int pos) const //const method is an accessor method
{
if(pos >= 12)
return 0;
*str = 'M'; //错误,不得修改该对象
return str[pos]; //return the value at position pos
}
}

Const和重载
重载函数的时候也可以使用const,考虑下面的代码:
class MyClass
{
char *str ="Hello, World";
MyClass()
{
//void constructor
}

~MyClass()
{
//destructor
}

char ValueAt(int pos) const //const method is an accessor method
{
if(pos >= 12)
return 0;
return str[pos]; //return the value at position pos
}

char& ValueAt(int pos) //通过返回引用设置内存内容
{
if(pos >= 12)
return NULL;
return str[pos];
}
}

在上面的例子中,ValueAt是被重载的。Const实际上是函数参数的一部分,在第一个成员函数中它限制这个函数不能改变对象的数据,而第二个则没有。这个例子只是用来说明const可以用来重载函数,没有什么实用意义。

实际上我们需要一个新版本的GetValue。如果GetValue被用在operator=的右边,它就会充当一个变量;如果GetValue被用作一元操作符,那么返回的引用可以被修改。这种用法常用来重载操作符。String类的operator[]是个很好的例子。(这一段译得很烂,原文如下:In reality due to the beauty of references just the second definition of GetValue is actually required. If the GetValue method is used on the the right side of an = operator then it will act as an accessor, while if it is used as an l-value (left hand side value) then the returned reference will be modified and the method will be used as setter. This is frequently done when overloading operators. The [] operator in String classes is a good example.)

class MyClass
{
char *str ="Hello, World";
MyClass()
{
//void constructor
}

~MyClass()
{
//destructor
}

char& operator[](int pos) //通过返回引用可用来更改内存内容
{
if(pos >= 12)
return NULL;
return str[pos];
}
}

void main(void)
{
MyClass m;
char ch = m[0]; //ch 等于 'H'
m[0] = 'M'; //m的成员str变成:Mello, World
}

Const的担心
C/C++中,数据传递给函数的方式默认的是值传递,也就是说当参数传递给函数时会产生一个该参数的拷贝,这样该函数内任何对该参数的改变都不会扩展到此函数以外。每次调用该函数都会产生一个拷贝,效率不高,尤其是函数调用的次数很高的时候。
例如:

class MyClass
{
public:
int x;
char ValueAt(int pos) const //const method is an accessor method
{
if(pos >= 12)
return 0;
return str[pos]; //return the value at position pos
}
MyClass()
{
//void constructor
}
~MyClass()
{
//destructor
}
MyFunc(int y) //值传递
{
y = 20;
x = y; //x 和 y 都等于 20.
}
}

void main(void)
{
MyClass m;
int z = 10;
m.MyFunc(z);
printf("z=%d, MyClass.x=%d",z,m.x); //z 不变, x 等于20.
}

通过上面的例子可以看出,z没有发生变化,因为MyFunc()操作的是z的拷贝。为了提高效率,我们可以在传递参数的时候,不采用值传递的方式,而采用引用传递。这样传递给函数的是该参数的引用,而不再是该参数的拷贝。然而问题是如果在函数内部改变了参数,这种改变会扩展到函数的外部,有可能会导致错误。在参数前加const修饰保证该参数在函数内部不会被改变。
class MyClass
{
public:
int x;
MyClass()
{
//void constructor
}
~MyClass()
{
//destructor
}
int MyFunc(const int& y) //引用传递, 没有任何拷贝
{
y =20; //错误,不能修改常变量
x = y
}
}

void main(void)
{
MyClass m;
int z = 10;
m.MyFunc(z);
printf("z=%d, MyClass.x=%d",z,m.x); //z不变, x等于10.
}

如此,const通过这种简单安全机制使你写不出那种说不定是什么时候就会掉过头来咬你一口的代码。你应该尽可能的使用const引用,通过声明你的函数参数为常变量(任何可能的地方)或者定义那种const method,你就可以非常有效确立这样一种概念:本成员函数不会改变任何函数参数,或者不会改变任何该对象的数据。别的程序员在使用你提供的成员函数的时候,不会担心他们的数据被改得一塌糊涂。
 

右左法则----复杂指针解析

右左法则----复杂指针解析
C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的:
The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.

这段英文的翻译如下:
右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。
        笔者要对这个法则进行一个小小的修正,应该是从未定义的标识符开始阅读,而不是从括号读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个。
        现在通过一些例子来讨论右左法则的应用,先从最简单的开始,逐步加深:
int (*func)(int *p);
首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是int。
int (*func)(int *p, int (*f)(int*));
func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int *和int (*)(int*)这样的形参,返回值为int类型。再来看一看func的形参int (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。
int (*func[5])(int *p);
func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰func的,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为int。

int (*(*func)[5])(int *p);
func被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。
int (*(*func)(int *p))[5];
func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。
要注意有些复杂指针声明是非法的,例如:
int func(void) [5];
func是一个返回值为具有5个int元素的数组的函数。但C语言的函数返回值不能为数组,这是因为如果允许函数返回值为数组,那么接收这个数组的内容的东西,也必须是一个数组,但C语言的数组名是一个右值,它不能作为左值来接收另一个数组,因此函数返回值不能为数组。
int func[5](void);
func是一个具有5个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组的元素除了类型必须一样外,每个元素所占用的内存空间也必须相同,显然函数是无法达到这个要求的,即使函数的类型一样,但函数所占用的空间通常是不相同的。
        实际当中,需要声明一个复杂指针时,如果把整个声明写成上面所示的形式,对程序可读性是一大损害。应该用typedef来对声明逐层分解,增强可读性,例如对于声明:
int (*(*func)(int *p))[5];
可以这样分解:
typedef  int (*PARA)[5];
typedef PARA (*func)(int *);
这样就容易看得多了。

一段有意思的代码

#include <iostream.h>
int *p = NULL;
int *fFun(void)
{
 int i = 0;
 return &i;
}
void subFun(void)
{
 (*p)--;
}
void gFun(void)
{
 int j;
 for(j = 0;j<10;j++)
 {
  subFun();
  cout<<j;
 }
}
int main(void)
{
 p = fFun();
 gFun();
 return 0;
}
上网看见了有一个有意思的代码.据说是一个公司的面试题目,很有意思
程序运行结果是死循环输出-1
分析一下这个程序
fFun()返回一个指针给P,P指向原来i的地址,i在函数调用的时候压栈,调用完了i出栈
但是这个地址被给了P,然后调用gFun,在gFun里j压栈,占了原来i的内存地址
这是P就指向了j,然后 (*p)--,j++,程序进入死循环....
25 febbraio

I/O流控制符

1)浮点显示控制
        a)setprecision(n)  :控制输出显示浮点数的数字个数(默认6)
        b)setprecision(n)+setiosflags(ios::fixed):控制定点输出表示小数位数
        c)setprecision(n)+setionsflags(ios::scientific):控制指数形式输出时小数位数
2)设置输出宽度setw(n)
3)设置输出形式八进制和十六进制
dec(十) 、oct(八)、hex(十六)
4)设置填充字符
setfill(‘')+setw(n)
5)设置对齐方式
setiosflags(ios::left)  (默认)
setiosflags(ios::right)
6)设置强制显示小数和符号
setiosflags(ios::showpoint)
setiosflags(ios::showpos)
28 dicembre

8086/8088 BIOS 中断

INT AH 功能 调用参数 返回参数
10

























 
0

























 
设置显示方式

 

 

 

 

 

 

 









 

AL=00 40×25黑白方式
AL=01 40×25彩色方式
AL=02 80×25黑白方式
AL=03 80×25彩色方式
AL=04 320×200彩色图形方式
AL=05 320×200黑白图形方式
AL=06 320×200黑白图形方式
AL=07 80×25单色文本方式
AL=08 160×200 16色图形 (PCjr)
AL=09 320×200 16色图形 (PCjr)
AL=0A 640×200 16色图形 (PCjr)
AL=0B 保留(EGA)
AL=0C 保留(EGA)
AL=0D 320×200 彩色图形 (EGA)
AL=0E 640×200 彩色图形 (EGA)
AL=0F 640×350 黑白图形 (EGA)
AL=10 640×350 彩色图形 (EGA)
AL=11 640×480 单色图形 (EGA)
AL=12 640×480 16色图形 (EGA)
AL=13 320×200 256色图形 (EGA)
AL=40 80×30 彩色文本(CGE400)
AL=41 80×50 彩色文本(CGE400)
AL=42 640×400 彩色图形(CGE400)
 
10
 
1
 
置光标类型
 
(CH)0-3=光标起始行
(CL)0-3=光标结束行
 
10
 
2
 
置光标位置
 
BH=页号
DH,DL=行,列
 
10
 
3
 
读光标位置
 
BH=页号
 
CH=光标起始行
DH,DL=行,列
10




 
4




 
读光笔位置




 
  AH=0 光笔未触发
  =1 光笔触发
CH=象素行
BX=象素列
DH=字符行
DL=字符列
10 5 置显示页 AL=页号  
10





 
6





 
屏幕初始化或上卷





 
AL=上卷行数
AL=0 整个窗口空白
BH=卷入行属性
CH=左上角行号
CL=左上角列号
DH=右下角行号
DL=右下角列号
 
10





 
7





 
屏幕初始化或下卷





 
AL=下卷行数
AL=0 整个窗口空白
BH=卷入行属性
CH=左上角行号
CL=左上角列号
DH=右下角行号
DL=右下角列号
 
10
 
8
 
读光标位置的字符和属性
 
BH=显示页
 
AH=属性
AL=字符
10


 
9


 
在光标位置显示字符及属性


 
BH=显示页
AL=字符
BL=属性
CX=字符重复次数
 
10

 
A

 
在光标位置显示字符

 
BH=显示页
AL=字符
CX=字符重复次数
 
10
 
B
 
置彩色调板(320×200图形)
 
BH=彩色调板ID
BL=和ID配套使用的颜色
 
10

 
C

 
写象素

 
DX=行(0-199)
CX=列(0-639)
AL=象素值
 
10
 
D
 
读象素
 
DX=行(0-199)
CX=列(0-639)
AL=象素值
 
10
 
E
 
显示字符
(光标前移)
AL=字符
BL=前景色
 
10
 
F
 
取当前显示方式
 
  AH=字符列数
AL=显示方式
10










 
13










 
显示字符串(适用AT)










 
ES:BP=串地址
CX=串长度
DH,DL=起始行,列
BH=页号
AL=0,BL=属性
串:char,char,...
AL=1,BL=属性
串:char,char,...
AL=2
串:char,attr,char,attr,...
AL=3
串:char,attr,char,attr,...



光标返回起始位置

光标跟随移动

光标返回起始位置

光标跟随移动
11









 
  设备检验









 
  AX=返回值
bit0=1,配有磁盘
bit1=1,80287协处理器
bit4,5=01,40×25BW(彩色板)
      =10,80×25BW(彩色板)
      =11,80×25BW(黑白板)
bit6,7=罗盘驱动器
bit9,10,11=RS-232板号
bit12=游戏适配器
bit13=串行打印机
bit14,15=打印机号
12   测定存储器容量   AX=字节数(KB)
13 0 软盘系统复位    
13 1 读软盘状态   AL=状态字节
13


 
2


 
读磁盘


 
AL=扇区数
CH,CL=磁盘号,扇区号
DH,DL=磁头号,驱动器号
ES:BX=数据缓冲区地址
读成功:AH=0
       AL=读取的扇区数
读失败:AH=出错代码
 
13

 
3

 
写磁盘

 
同上

 
写成功:AH=0
       AL=写入的扇区数
写失败:AH=出错代码
13

 
4

 
检验磁盘扇区

 
同上(ES:BX不设置)

 
成功:AH=0
     AL=检验的扇区数
失败:AH=出错代码
13
 
5
 
格式化盘磁道
 
ES:BX=磁道地址
 
成功:AH=0
失败:AH=出错代码
14
 
0
 
初始化串行通讯口
 
AL=初始化参数
DX=通讯口号(0,1)
AH=通读口状态
AL=调制解调器状态
14


 
1


 
向串行通讯口写字符


 
AL=字符
DX=通讯口号(0,1)

 
写成功:(AH)7=0
写失败:(AH)7=1
(AH)0-6=通讯口状态
14


 
2


 
从串行通讯口读字符


 
DX=通讯口号(0,1)


 
读成功:(AH)7=0
       (AL)=字符
写失败:(AH)7=1
(AH)0-6=通讯口状态
14
 
3
 
取通讯口状态
 
DX=通讯口号(0,1)
 
AH=通讯口状态
AL=调制解调器状态
15 0 启动盒式磁带马达    
15 1 停止盒式磁带马达    
15



 
2



 
磁带分块读



 
ES:BX=数据传输区地址
CX=字节数


 
AH=状态字节
AH=00 读成功
  =01 冗余检验错
  =02 无数据传输
  =04 无引导
15
 
3
 
磁带分块写
 
DS:BX=数据传输区地址
CX=字节数
同上
 
16 0 从键盘读字符   AL=字符码
AH=扫描码
 
16

 
1

 
读键盘缓冲区字符

 
  ZF=0 AL=字符码
     AH=扫描码
ZF=1 缓冲区空
16 2 读键盘状态字节   AL=键盘状态字节
17
 
0
 
打印字符
回送状态字节
AL=字符
DX=打印机号
AH=打印机状态字节
 
17
 
1
 
初始化打印机
回送状态字节
DX=打印机号
 
AH=打印机状态字节
 
17 2 取状态字节 DX=打印机号 AH=打印机状态字节
1A
 
0
 
读时钟
 
  CH:CL=时:分
DH:DL=秒:1/100秒
1A
 
1
 
置时钟
 
CH:CL=时:分
DH:DL=秒:1/100秒
 
1A
 
2
 
读实时钟
 
  CH:CL=时:分(BCD)
DH:DL=秒:1/100秒(BCD)
1A 6 置报警时间 CH:CL=时:分(BCD)
DH:DL=秒:1/100秒(BCD)
 
1A 7 清除报警    
26 dicembre

剖析浮点数的存储形式

众所周知,浮点数(float)在计算机中占4byte32bit,这32bit是如何表示一个浮点数的那?经过查资料,我们得知,浮点数是按照如下格式进行存储的:

例如:0.5的二进制形式是0.1

它用浮点数的形式写出来是如下格式

               01111110                 00000000000000000000000

符号位           阶码                       小数位

正数符号位为0,负数符号位为1

阶码是以2为底的指数

小数位表示小数点后面的数字

 

下面我们来分析一下0.5是如何写成0  01111110  00000000000000000000000

 

首先0.5是正数所以符号位为0

再来看阶码部分,0.5的二进制数是0.1,0.11.0*2^(-1),所以我们总结出来:

要把二进制数变成(1.f)*2^(exponent)的形式,其中exponent是指数

而由于阶码有正负之分所以阶码=127+exponent;

即阶码=127+(-1)=126 01111110

余下的小数位为二进制小数点后面的数字,00000000000000000000000

 

由以上分析得0.5的浮点数存储形式为0  01111110  00000000000000000000000

 

现在我们明白了一个数是如何表示成浮点数形式,下面我们来编一个c++程序来验证它.

C++代码如下:

 

#include <iostream.h>

void main()

{

         float f;

         int a[4][8];

 

         cin>>f;

         unsigned char b[4];

         for(int i=0;i<4;i++)

         {

                   b[i]=*((char *)&f+i);

         }

         for(i=0;i<4;i++)

         {

                   int temp=b[i];

                   for(int j=0;j<8;j++)

                   {

                            a[i][j]=temp%2;

                            temp/=2;

                   }

         }

         cout<<a[3][7]<<" ";

         for(i=6;i>=0;i--)

         {

                   cout<<a[3][i];

         }

         cout<<a[2][7]<<" ";

         for(i=6;i>=0;i--)

         {

                   cout<<a[2][i];

         }

         for(i=1;i>=0;i--)

         {

                   for(int j=7;j>=0;j--)

                   {

                            cout<<a[i][j];

                   }

         }

         cout<<endl;

}

数字

符号位

阶码

小数位

0.5

0

01111110

00000000000000000000000

0.625

0

01111110

01000000000000000000000

-3.25

1

10000000

10100000000000000000000

0.725

1

01111110

01110011001100110011010

俄罗斯方块汇编源代码

;       Tetris
; Written by Lim GumSu(prk)
;     2005.12.12 Nankai University

DATA    SEGMENT
 SEGMENT1C DW 0
 OFF1C DW 0
 BOARD DW 24 DUP(?),0FFFFH
 Y DB ?
 TY DB ?
 XR DB ?
 XL DB ?
 NOW DB ?
 DIRE DB ?
 NXT DB ?
 TIM DB 0
 SPEED DB 0
 CON DB 0
 DV DB      0
 FLG DB  0
 PAD DW 0H,3C0H,0H,0H ;0
  DW 100H,100H,100H,100H
  DW 0H,3C0H,0H,0H
  DW 100H,100H,100H,100H
  DW 0H,180H,180H,0H ;1
  DW 0H,180H,180H,0H
  DW 0H,180H,180H,0H
  DW 0H,180H,180H,0H
  DW 0H,380H,200H,0H ;2
  DW 200H,200H,300H,0H
  DW 0H,80H,380H,0H
  DW 0H,300H,100H,100H
  DW 0H,380H,80H,0H ;3
  DW 300H,200H,200H,0H
  DW 0H,200H,380H,0H
  DW 100H,100H,300H,0H
  DW 0H,180H,300H,0H ;4
  DW 100H,180H,80H,0H
  DW 0H,180H,300H,0H
  DW 100H,180H,80H,0H
  DW 0H,300H,180H,0H ;5
  DW 80H,180H,100H,0H
  DW 0H,300H,180H,0H
  DW 80H,180H,100H,0H
  DW 0H,380H,100H,0H  ;6
  DW 100H,180H,100H,0H
  DW 100H,380H,0H,0H 
  DW 100H,300H,100H,0H
 P1 DW 4 DUP(?)
 P2 DW 4 DUP(?)
        COLOR   DB      00001001b,00001010b,00001011b,00001100b,00001101b,00001110b,00000001b
 NCOLOR DB ?
 SCORE DB 5 DUP('0'),'$'
 PADMSG DB 25 DUP(219)
 TMPMSG DB 25 DUP(?)
 STARTMSG1 DB 0DH,0AH,'Select speed.',0DH,0AH,'$'
        STARTMSG2       DB      20H,20H,'1. Fast',0DH,0AH,'$'
 STARTMSG3 DB 20H,20H,'2. Middle',0DH,0AH,'$'
        STARTMSG4       DB      20H,20H,'3. Slow',0DH,0AH,'$'
 STARTMSG5 DB 20H,20H,'0. Exit',0DH,0AH,'$'
 ENDMSG  DB 0DH,0AH,'Good Bye!',0DH,0AH,'$'
        SCOREMSG1       DB      201,19 dup(205),187
        SCOREMSG2       DB      186,'  Score:           ',186
        SCOREMSG3       DB      204,19 dup(205),185
        SCOREMSG4       DB      186,19 dup(32),186
        SCOREMSG5       DB      186,19 dup(32),186
        SCOREMSG6       DB      186,19 dup(32),186
        SCOREMSG7       DB      186,19 dup(32),186
        SCOREMSG8       DB      204,19 dup(205),185
        SCOREMSG9       DB      186,'   Left  : A       ',186
        SCOREMSG10      DB      186,'   Right : D       ',186
        SCOREMSG11      DB      186,'   Rotate: S       ',186
        SCOREMSG12      DB      186,'   Down  : Tab     ',186
        SCOREMSG13      DB      186,'-------------------',186
        SCOREMSG14      DB      186,'   Exit  : Esc     ',186
        SCOREMSG15      DB      200,19 dup(205),188
DATA ENDS

STACK SEGMENT STACK
 DB 200 DUP(?)
STACK ENDS

CODE SEGMENT
 ASSUME  CS:CODE,DS:DATA,ES:DATA,SS:STACK
START:  MOV AX,DATA
 MOV DS,AX
 PUSH DS
 ;GET INT 1C ADRESS
 MOV AL,1CH
 MOV AH,35H
 INT 21H
 MOV SEGMENT1C,ES
 MOV OFF1C,BX
 ;SET INT 1C ADRESS
 MOV DX,OFFSET INT1C
 MOV AX,SEG INT1C
 MOV DS,AX
 MOV AL,1CH
 MOV AH,25H
 INT 21H
 POP DS
 
GAMEOVER: 
 MOV AH,00H
 MOV AL,03H
 INT  10H
SELECTSPEED:
 MOV AH,09H
 MOV DX,OFFSET STARTMSG1
 INT 21H
 MOV DX,OFFSET STARTMSG2
 INT 21H
 MOV DX,OFFSET STARTMSG3
 INT 21H
 MOV DX,OFFSET STARTMSG4
 INT 21H
 MOV DX,OFFSET STARTMSG5
 INT 21H
 MOV AH,08H
 INT  21H
 SUB AL,'0'
 MOV CL,AL
 AND AL,3
 CMP AL,CL
        JNE     SELECTSPEED
        INC AL
 INC CL
 MUL CL
        CMP     AL,1H
        JE      EXIT
 MOV SPEED,AL
  
 ;SET GRAPHICS
 MOV AH,00H
 MOV AL,12H
 INT 10H
 MOV AH,0BH
 MOV BH,01
 MOV BL,00H
 INT 10H
 ;START  GAME
 CALL INITGAME
 CALL BEGIN
 CALL  DELAY
 MOV TIM,0H
LOOP1: STI
 MOV AL,TIM
 CMP AL,SPEED
 JG TIME
        MOV  AH,1
        INT  16H
        JZ  LOOP1
        MOV  AH,0
        INT  16H
        CMP  AL,1BH
        JZ  EXIT
        CMP AL,'a'
        JZ KA
        CMP AL,'s'
        JZ KS
        CMP AL,'d'
        JZ KD
        CMP     AL,09H
        JNZ     TIME
KTAB:   CALL DELAY
 CALL  DOWN
        CMP  CON,1
        JNE KTAB
        CALL  BEGIN
        JMP     LOOP1
KA: CALL LEFT
 JMP  LOOP1
KS: CALL   ROTATE
 JMP LOOP1
KD: CALL  RIGHT
 JMP LOOP1
TIME: MOV TIM,0H
 CALL DOWN
 CMP CON,0
 JE LOOP1
 CALL BEGIN
 JMP LOOP1

EXIT: ;SET GRAPHICS
 MOV AX,0003H
 INT  10H
 MOV AX,DATA
 MOV DS,AX
 MOV DX,OFFSET ENDMSG
 MOV AH,09H
 INT  21H
 ;SET INT 1C ADRESS
 MOV DX,OFF1C
 MOV AX,SEGMENT1C
 MOV DS,AX
 MOV AL,1CH
 MOV AH,25H
 INT 21H
 MOV AX,4C00H
 INT 21H

INT1C PROC
 STI
 PUSH AX
 PUSH DX
 MOV AX,DATA
 MOV DS,AX
 INC TIM
 POP  DX
 POP AX
 IRET
INT1C ENDP

DELAY PROC NEAR
 PUSH CX
        MOV     CX,00FFH
LOOP20: LOOP    LOOP20
 POP CX
 RET
DELAY ENDP
 
ROTATE PROC NEAR
 MOV SI,OFFSET PAD
 MOV AL,NOW
 MOV AH,0H
 MOV CL,32
 MUL CL
 ADD SI,AX
 MOV AL,DIRE
        INC     AL
 AND AL,03H
 MOV AH,0H
 MOV CL,8
 MUL CL
 ADD SI,AX
 MOV DI,OFFSET P2
 MOV CX,04H
 CLD
LOOP12: PUSH    CX
        LODSW
        MOV     CL,XR
        SHR     AX,CL
        MOV     CL,XL
        SHL     AX,CL
 STOSW
        POP     CX
        LOOP    LOOP12

 CALL  CHECK
 CMP AL,0H
 JNE SKIP10
 MOV BX,0000H
 CALL DISPPAD
 
 CALL  COPY21
 INC DIRE
 AND DIRE,3H 
 MOV BH,00H
 MOV BL,NCOLOR
 CALL  DISPPAD
SKIP10: RET
ROTATE ENDP

RIGHT PROC NEAR
 CALL  COPY12
 MOV SI,OFFSET P2
 MOV CX,04H
LOOP7: MOV AX,[SI]
 SHR AX,1
 MOV [SI],AX
 INC SI
 INC SI
 LOOP  LOOP7
 CALL  CHECK
 CMP AL,0H
 JNE SKIP6
 MOV BX,0000H
 CALL DISPPAD
 CALL  COPY21
 
 CMP XL,0
 JE SKIP7
 DEC XL
 DEC XR
SKIP7:  INC XR

 MOV BH,00H
 MOV BL,NCOLOR
 CALL  DISPPAD

SKIP6: RET
RIGHT ENDP

LEFT PROC NEAR
 CALL  COPY12
 MOV SI,OFFSET P2
 MOV CX,04H
LOOP10: MOV AX,[SI]
 SHL AX,1
 MOV [SI],AX
 INC SI
 INC SI
 LOOP  LOOP10
 CALL  CHECK
 CMP AL,0H
 JNE SKIP8
 MOV BX,0000H
 CALL DISPPAD
 CALL  COPY21
 
 CMP XR,0
 JE SKIP9
 DEC XR
 DEC XL
SKIP9:  INC XL

 MOV BH,00H
 MOV BL,NCOLOR
 CALL  DISPPAD

SKIP8: RET
LEFT ENDP

DOWN PROC NEAR
 CALL  COPY12
 INC TY
 CALL  CHECK
 CMP AL,0H
 JNE SKIP5
 MOV BX,0000H
 CALL DISPPAD
 CALL  COPY21
 MOV BH,00H
 MOV BL,NCOLOR
 CALL  DISPPAD
 MOV CON,00H
 RET
SKIP5:  CALL    PUT
 MOV CON,01H
 RET
DOWN  ENDP

PUT     PROC    NEAR
 MOV BH,0H
        MOV     BL,0h
 CALL DISPPAD
 MOV BH,0H
        MOV     BL,01011001b
 CALL DISPPAD

 INC SCORE[4]
 MOV DV,01H
 MOV AH,0H
 MOV AL,Y
 ADD AL,Y
 MOV SI,OFFSET BOARD
 ADD SI,AX
 MOV DI,00H
 MOV CX,04H
 CLD
LOOP15: LODSW
        OR      AX,P1[DI]
        MOV     [SI-2],AX
 INC DI
 INC DI
        LOOP  LOOP15

        MOV     SI,OFFSET BOARD
        ADD     SI,23*2
        MOV     DI,SI
        MOV     CX,20
        MOV     BH,00H
       
        MOV FLG,00H
        STD
LOOP13: LODSW
        CMP     AX,0FFFFH
        JNE     SKIP12
        MOV FLG,0FFH
        MOV AL,DV
        SAL AL,1
        MOV DV,AL
        JMP  LOOP13
SKIP12: STOSW
 ;PUSH AX
 CMP FLG,0H
 JE      SKIP70
 PUSH    CX
        MOV     DH,CL
        ADD     DH,03H

        MOV     DL,0AH
        MOV     BX,0000H
        MOV     BP,OFFSET PADMSG
        MOV     CX,20
        PUSH    AX
        MOV     AX,1300H
        INT     10H
        POP     AX

 MOV  CL,03H
 SHL AX,CL
 MOV CX,0AH
 MOV DL,08H
LOOP14: INC     DL
 INC DL
        MOV     BL,0H
 SHL AX,1
        JNC     SKIP11
        MOV     BL,01011001b
SKIP11: CALL    DISPCELL
        LOOP    LOOP14
 POP CX
SKIP70: LOOP    LOOP13
       
        MOV AL,DV
        SAR AL,1
        ADD SCORE[3],AL
        MOV CX,05H
        MOV SI,04H
LOOP16: CMP SCORE[SI],'9'
 JNG SKIP13
 INC SCORE[SI-1]
 SUB SCORE[SI],0AH
SKIP13: DEC SI
 LOOP LOOP16
        RET
PUT     ENDP

DISPSCORE PROC NEAR
 MOV AX,DATA
 MOV ES,AX
 MOV BP,OFFSET SCORE
 MOV CX,05H
        MOV     DX,0635H
 MOV BH,0H
 MOV AL,0H
 MOV BL,00110100B
 MOV AH,13H
 INT 10H
 RET
DISPSCORE ENDP

DISPNEXT PROC NEAR
 MOV AX,DATA
 MOV ES,AX
 MOV BP,OFFSET TMPMSG
 MOV DI,BP
 MOV SI,OFFSET PAD
 MOV AL,NXT
 MOV AH,0
 MOV BL,32
 MUL BL
 ADD SI,AX

 CLD
 MOV CX,04H
LOOP8: PUSH CX
 LODSW  
 MOV CL,06H
 SHL AX,CL
 MOV CX,04H
LOOP9:  MOV     BL,20H
 SHL AX,1
 JNC SKIP2
 MOV BL,219
SKIP2: MOV [DI],BL
 INC DI
 MOV [DI],BL
 INC DI
 LOOP LOOP9
        MOV     DX,0c30H
 POP  CX
 SUB  DH,CL
 PUSH  CX
 MOV CX,08H
 MOV BH,0H
 PUSH SI
 MOV  AH,0H
 MOV  AL,NXT
 MOV  SI,AX
 MOV  BL,COLOR[SI]
 POP  SI
        MOV     AX,1300H
 INT 10H
 POP CX
 MOV DI,BP
 LOOP LOOP8
 RET
DISPNEXT ENDP

COPY21 PROC NEAR
 CLD
 MOV SI,OFFSET P2
 MOV DI,OFFSET P1
 MOV CX,08
 REP MOVSB
 MOV  CL,TY
 MOV Y,CL
 RET
COPY21 ENDP

COPY12 PROC NEAR
 CLD
 MOV SI,OFFSET P1
 MOV DI,OFFSET P2
 MOV CX,08
 REP MOVSB
 MOV  CL,Y
 MOV TY,CL
 RET
COPY12 ENDP

BEGIN PROC NEAR
 MOV AL,NXT
 MOV NOW,AL
 CALL RANDOM
 CALL DISPSCORE
 CALL DISPNEXT
 ;FORMAT VALUE
 MOV DIRE,0
 MOV Y,4
 MOV TY,4
 MOV XR,0
 MOV XL,0
 MOV AH,0
 MOV AL,NOW
 MOV SI,AX
 MOV CL,COLOR[SI]
 MOV NCOLOR,CL
 MOV DI,OFFSET P2
 MOV SI,OFFSET PAD
 MOV BL,32
 MUL BL
 ADD SI,AX

 MOV CX,08
 CLD
 REP  MOVSB

 CALL COPY21
 MOV BH,0H
 MOV BL,NCOLOR
 CALL DISPPAD
 CALL CHECK
 CMP AL,0
 JE SKIP1
 MOV DL,07H
 MOV AH,02H
 INT  21H
 MOV AH,08H
 INT  21H
 JMP GAMEOVER
SKIP1: CALL DELAY
 MOV TIM,0H
 RET
BEGIN ENDP

CHECK PROC NEAR ;RETURN  AL=0/F  0:OK  F:NO
 MOV AH,0H
 MOV AL,TY
 ADD AL,TY
 MOV SI,OFFSET BOARD
 ADD SI,AX
 MOV DI,00H
 MOV CX,04H
 CLD
LOOP6: LODSW
 AND  AX,P2[DI]
 JNZ SKIP4
 INC DI
 INC DI
 LOOP  LOOP6
 MOV AL,00H
 RET
SKIP4:  MOV AL,0FH
 RET
CHECK ENDP

DISPPAD PROC NEAR   ;BX BH=PAGE BL=COLOR
 MOV  SI,OFFSET P1
 MOV  CX,04H
 MOV DL,08H
 MOV  DH,Y
 ADD DH,04H
 PUSH DX
 CLD
LOOP2: LODSW 
 POP DX
 PUSH DX
 SUB DH,CL
 PUSH  CX
 MOV  CL,03H
 SHL AX,CL
 MOV CX,0AH
LOOP3: INC DL
 INC DL
 SHL AX,1
 JNC SKIP3
 CALL  DISPCELL 
SKIP3: LOOP LOOP3
 POP CX
 LOOP  LOOP2
 POP DX
 RET
DISPPAD ENDP

DISPCELL PROC NEAR ;DH=ROW DL=COL BH=PAGE BL=COLOR
 PUSH AX
 PUSH BX
 PUSH CX
 PUSH DX
 PUSH DI
 PUSH SI
 MOV BP,OFFSET PADMSG
 MOV CX,02H
 MOV AX,1300H
 INT  10H
 CMP BL,0H
 JE SKIP20
 ;CALC ROW
 MOV AH,0H
 MOV AL,DH
        MOV     CL,16
 MUL CL
 MOV SI,AX
 ;CALC COL
 MOV AH,0H
 MOV AL,DL
 MOV CL,8
 MUL CL
 MOV DI,AX
 ;DRAW
 MOV AX,0C00H
 MOV DX,SI
        ADD     DX,15
 MOV CX,16
LOOP21: ADD CX,DI
 DEC CX
 INT 10H
 INC CX
 SUB CX,DI
 LOOP LOOP21
 
        MOV     DX,SI
        MOV     CX,15
        ADD     DI,15
LOOP22: PUSH    CX
        MOV     CX,DI
        INT     10H
        INC     DX
        POP     CX
        LOOP    LOOP22

        SUB     DI,2
        DEC     DX
        MOV     CX,13
LOOP23: PUSH    CX
        DEC     DX
        MOV     CX,DI
        INT     10H
        SUB     CX,12
        MOV     AL,07H
        INT     10H
        MOV     AL,00H
        POP     CX
        LOOP    LOOP23

        MOV     AX,0C07H
 MOV DX,SI
        ADD     DX,1
        MOV     CX,12
        SUB     DI,12
LOOP24: ADD     CX,DI
 INT 10H
 SUB CX,DI
        LOOP    LOOP24
 
SKIP20: POP SI
 POP DI
 POP DX
 POP CX
 POP BX
 POP AX
 RET
DISPCELL ENDP
 
CLS PROC NEAR
 MOV CX,0
 MOV DH,24
 MOV DL,79
 MOV BH,0
 MOV AX,600H
 INT 10H
 RET
CLS ENDP

RANDOM PROC NEAR
LOOP5:  IN      AX,40H
        INC  AL
 AND AL,07H
 CMP AL,07H
 JE LOOP5
 MOV NXT,AL
 RET
RANDOM ENDP

INITGAME PROC NEAR
 CALL CLS
 ;DRAW   TEXTFRAME
 MOV AX,DATA
 MOV ES,AX
        MOV     CX,15
 MOV BP,OFFSET SCOREMSG1
        MOV     DX,052aH
LOOP72: PUSH CX
        MOV     CX,21
 MOV AL,0H
 MOV BH,0H
        MOV     BL,01011010B
 MOV AH,13H
 INT 10H
        ADD     BP,21
 INC DH
 POP CX
 LOOP LOOP72
 
 ;DRAW BOARDFRAME
 MOV BP,OFFSET PADMSG
        MOV     CX,0024
        MOV     DX,0308H
 MOV BH,0H
 MOV AL,0H
 MOV BL,00110100B
 MOV AH,13H
 INT 10H
        MOV     DX,1808H
 INT 10H

 MOV CX,20
        MOV     DX,0308H
LOOP4: MOV SI,CX
 MOV CX,02
 INC DH
 INT 10H
 MOV CX,SI
 LOOP LOOP4

 MOV CX,20
        MOV     DX,031EH
LOOP11: MOV SI,CX
 MOV CX,02
 INC DH
 INT 10H
 MOV CX,SI
 LOOP LOOP11
 ;FORMAT BOARD
 CLD
 MOV DI,OFFSET BOARD
 MOV CX,24
 MOV  AX,0E007H
 REP STOSW
 ;FORMAT SCORE
 MOV DI,OFFSET SCORE
 MOV AL,'0'
 MOV CX,05H
 REP STOSB
 CALL RANDOM
 MOV AL,NXT
 MOV NOW,AL
 RET
INITGAME ENDP

CODE ENDS
 END START

 

24 dicembre

Bresenham画线算法

假设x列的象素已确定,其行下标为y。那么下一个象素的列坐标必为x+1。而行坐标要么不变,要么递增1。是否递增1取决于如图所示的误差项d的值。因为直线的起始点在象素中心,所以误差项d的初始值为0。X下标每增加1,d的值相应递增直线的斜率值,即d=d+k(k=y/x为直线斜率)。一旦d>=1时,就把它减去,这样保证d始终在0、1之间。当d>0.5时,直线与x+1垂直网络线交点最接近于当前象素(x,y)的右上方象素(x+1,y+1);而当d<0.5时,更接近于象素(x+1,y),当d=0。5时,与上述二象素一样接近,约定取(x+1,y+1)。令e=d-0。5。则当e>=0时,下一象素的y下标增加1,而当e〈0时,下一象素的y下标不增。E的初始值为-0.5.

破解所谓的“网页源代码加密”

在地址栏或按Ctrl+O,输入:

javascript:s=document.documentElement.outerHTML;document.write('<body></body>');document.body.innerText=s;

源代码就出来了。不论加密如何复杂,最终都要还原成浏览器可以解析的html代码,而documentElement.outerHTML正是最终的结果。