检测比较结果的条件转移指令
转移是指它可以修改ip,条件指在某种特定情况下才会修改
例如 jcxz就是一个条件转移指令,只有在cx=0的情况下才会跳转
下列转移指令都是根据cmp指令进行的转移
无符号数情况下的转移
指令
含义
检测的标志位
je
等于则转移
zf=1
jne
不等于则转移
zf=0
jb
小于则转移
cf=1
jnb
大于等于则转移
cf=0
ja
高于则转移
cf=0且zf=0
jna
不高于则转移
cf=1或zf=1
记忆方法:第一个字母都是j,代表jump
e:equal
ne:not equal
b:below
a:above
不一定要在前面是cmp指令,例如mov ax,0je sinc axs: inc ax
数论
整除如果a能被b整除,a=b*q,q为一整数记作b|a,a是被除的那个
同余如果a和bmod m 是同一个值,则称a和b同余,记作a (三横线) b(mod m)
例如: 3 和 8 关于5 同余 因为 3%5=3,8%5=3
重要性质:
(a+b)%c=a%c+b%c
(a*b)%c=(a%c*b%c)%c
(a^b)%c=(a%c^b)%c
唯一分解定理任何大于1的正整数n都可以被分解为若干质数的乘积
约数个数 例如 72=2^33^2 ,而72有 1 2 3 4 6 8 9 12 18 24 36 72 12个约数,而我可以从2^3 中提取出0个2,1个2,两个2,三个2把其他的数放到另一边,这样我们就可以得到4个约数,3也同理,用一下分配率,就可以得到约数个数为34=12
约数和 因为约数是从2和3中随机挑出若干个数进行分配,所以用分配率可得约数和为
(1+2+2^2+2^3)(1+3+3^2)
费马小定理如果p是质数且a与p互质,则
a^(p-1)%p=1(a的p-1次方和1关于p同余)
互质指的是 二者除了1以外没有相同的约数
求质数 ...
栈.
栈是一段连续的内存空间,这个空间的特殊性在于,最后进入这个空间的数据,最先出去
原理通过ss sp 两个寄存器确定了一个栈顶指针,然后随着一些操作,这个指针会向上向下移动例如 push ax,这条指令会将ax中的内容运到栈中,然后sp-2。注意,栈顶地址为低地址,栈底地址为高地址,因此增加元素会使sp值减小
在栈为空的时候,偏移地址为栈底地址加2,例如栈底为000F,则此时偏移地址为10,在拉一个元素进栈后,偏移地址为000E,恰好是数据最高位(一个数据一个字,两个字节,栈底为000F,用了两个空间,因此此时元素到了000E,恰好sp也是000E
超界问题8086cpu并没有特定的机制来检查我们是否超界,只能够靠自己小心,超界是一个十分严重的问题,因为既然这一段被分配为栈了,说明其他的内存有其他的用途,如果超界,可能会干扰其他程序的运行。要注意,栈的范围最大是0到ffff即2的16次方字节
push pop 命令push 寄存器 pop 寄存器也可以是push内存地址,pop内存地址
快速输入
inline int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; }
这个快速输入只适合int类型,另外如果参加比赛,最好不要用cin,cout,速度较慢用scanf,printf更好
操作符offset
offset是由编译器处理的符号,它的功能是获得标号的偏移地址
例code segmentstart: mov ax,offset start//相当于mov ax,0 s: mov ax,offset s//相当于mov ax,3code ends上面的程序中offset获得了start和s的偏移地址0和3
归并排序
基本原理归并排序运用了分治的思想,先将数组二分成一个元素(一个元素时看为有序),然后将这些元素不断合并,每合并一次排一次序,最后就可以得到有序的数组。
比如说一个序列:12 ,23,1,44,233,10,9,8。我们先分成两段:12 ,23,1,44 和 233,10,9,8,发现还能再分成4段:12 ,23 和 1,44———233,10 和 9,8。再分成8段:12—23—1—44 和233—10—9—8。这时候开始把子序列进行排序合并,一个元素就是有序的。所以不用排序。合并成2个一组排序得到:12,23——1,44—-10,233—-8,9。再合并成4个一组排序得到:1,12,23,44—-8,9,10,233。最后合并得到最终结果:1,8,9,10,12,23,44,233。
合并过程看代码
链接:https://www.jianshu.com/p/b50a6034eb90
图解
这个图片蓝色部分就是拆的过程,而绿的部分为并的过程
代码实现void paixu(int first,int mid,int last,int a[],int temp[])//这是合并过程 ...
开始使用unix
当你使用Unix系统的时候,第一件要你做的事便是输入用户标识和口令(账号密码),注意,在Unix中,密码是完全不可见的,甚至连*号都不会出现。
登陆之后出现的欢迎界面,这一部分源于一个特殊的初始化文档,这就意味着你可以对文档内容进行修改从而定制化你的初始化界面。
一旦初始化命令结束执行,Unix将启动shell,并将控制权交给他。这时shell会出现一个提示-称为shell提示,并等待命令。接下来就可以输入各种命令了。
最终,没有命令时,你可以通过注销结束工作会话,此时shell将停止运行。
宏定义
宏定义就是在开始用井号(#)定义一个函数或者是常量,这种定义在编译器中被处理,运算速度快,但使用宏定义时可能会出现一些隐蔽的问题
例如:
#define DATA sizeof(int)for(int i=cnt;i-DATA>=0;i-=DATA)
乍一看这样做似乎没什么问题,要注意sizeof返回的是一个无符号数,有符号数和无符号数做比较的时候会先把有符号数变成无符号数。而负数的有符号数最高位一定为1,这样就可能会导致数据异常。
将不同代码放入不同段中
举个栗子
assume cs:code ds:data ss:stackdata segment dw 0123h,0345hdata endsstack segment dw 0,0,0,0,0,0stack endscode segment start: mov ax,stack mov ss,ax mov sp,20h mov ax,data mov ds,ax mov bx,0 //ds:bx指向data中第一个内存单元 mov cx,8 s: push [bx] add bx,2 loop s mov bx,0 mov cx,8 s0:pop [bx] add bx,2 loop s0 mov ax,4c00h int 21h code endsend start
看了这个就差不多了,前面定义的时候要注意不同段对应不同的寄存器,而后面要注意各个段有独自的segmen ...
并查集
并查集指的是一个图中的若干个连通分支,任意两个连通分支间没有关系,而每个连通分支内部可以以任意一个点作为根节点,根节点指向它自己,而其他点指向他们的上级节点(因为是连通图,两点之间必定可达),因此只要在同一连通分支,必定可以到同一根节点,从而判断两者可达
例如:pre[2]=3表示2的上级节点为3,pre[3]=3表示这是一个根节点
int find(int x) //查找我(x)的掌门{ int r=x; //委托 r 去找掌门 while (pre[r ]!=r) //如果r的上级不是r自己(也就是说找到的大侠他不是掌门 = =) r=pre[r ] ; // r 就接着找他的上级,直到找到掌门为止。 return r ; //掌门驾到~~~}
另外如何将两个连通分支合并为一个连通分支呢?
我们可以把任意一个根节点指向另外一个根节点(因为我们不考虑内部的关系,指向知道是否可达) ...