涉及到的文章例子大都测试有效
字符串概念
基本字符串操作指令:
CMPSB有个缺陷是比较字符串一定要长度相同,不等就是0填充
还有个CMPS注意就好
CMPSB的例子:
SCASB,SCASW 和SCASD 指令把ALAX/EAX 中的值同由EDI寻址的目标内存中的字节字或双字相比较。
,这些指令在一个长字符串或数组中查找一个值的时候特别有用如果使用REPE(或REP) 前缀, 当ECX>0
并且AL/AX/EAX 匹配内存中的值时,指令继续扫描字符串或数组REPNE 前缀使得指令扫描字符串,
直到AL/AX/EAX 匹配内存中的一个值或ECX=0 时停止。
例子:
字符删除和这个一样 只不过用REPE伪指令 相等则停下
STOSB,STOSW和STOSD指令把ALAX/EAX的内容存储在EDI指向的内存单元中,
同时EDI的值根据方向标志的值增加或减少。同REP前缀联合使用的时候,这组指令在需要以指定的字符
例子:填充字符串
LODSB,LODSW和LODSD指令从ESI指向的内存位置向AL/AX/EAX 中装人一个值,同寸
ESI 的值根据方向标志值增加或减少。
我们很少把REP 前缀同LODS 指令联用,因为装人到累加
相反,一般仅用LODS 指令来装人一个值。例如LODSB
器中的每个新值都会覆盖掉以前的值,
指令可以替代下面的两条指令( 假设方向标志已清零):
moval,[esi];传送一个字节至AL
in esi;指向下一个字节
以上的每条指令都会隐晦的使用ESI和EDI寄存器 很关键
在保护模式下 ESI为DS的段内偏移 EDI为ES的段内偏移
DS与ES的值总是相同的
字符串中使用重复前缀十分的重要,因为使用重复前缀可以多次操作字符串
例子: 复制字符串。在下面的例子中,MOVSB 指令从string1中移动10 个字节到string2,在执行MOVSB 指令之前,
重复前缀首先测试ECX 是否大于0。如果ECX 等于0,则执行程序中的下一条指令。如果ECX>0,那么ECX减1并重复执行该指令:
其中方向标志很重要:STD CLD
方向标志: 字符串指令根据方向标志的状态使ESI 和EDI 增加或减少( 见表9.2),方向标志可以通过CLD 和STD指令显式地修改:
CLD ;清除方向标志
STD ;设置方向标志
在执行字符串操作指令之前忘记设置方向标志可能导致非常令人头疼的问题
,在执行时由于方向标志值的不确定性,多次执行的结果可能会非常地不一致。
二维数组
字符串和数组实际上是一样的,只不过是字符串以0结尾
二维数组的形式
从汇编语言程序员的视角来看,二维数组是一维数组的高阶抽象。
对于二维数组在内存中行列的存储,高级语言一般采用下面的两种方法: 行主序( row-majororder )和列主序( column-majororder).
使用行主序存储(最常使用)时,第一行放在内存块的开始,第一行的最后一个元素后接第二行的第- 一个元素。使用列主序存储时,
第一列的元素放在内存块的开始,第一列的最后一个元素后接第二列的第一个元素。
行主序( row-majororder ):也就是算出某一行的地址,然后加上列的位置,记住列的Index要乘以这个数组的类型,也就是WORD还是DWORD还是其他
基址变址操作:
基址变址(base-index )操作数把两个寄存器的值相加,得到一个偏移地址。
两个寄存器分别称为基址(base )和变址(index)。,格式如下:
[base + index]
格式中的方括号是必需的。在32 位模式下,基址和变址部分均可使用任意32 位通用寄存器; 在
16位模式下,基址寄存器必须是BX 或BP (除非是寻址堆栈上的数据,否则应尽量避免使用BP或EBP作为基址寄存器),变址寄存器必须是SI 或DI。
所谓的基址变址操作:就是base是array偏移+行偏移,index是列偏移而已
相对基址变址操作:
也不过是用数组变量名么,但是base仅仅是行偏移,index是列偏移
格式如下:
实际上就是
array[行偏移+列索引乘以TYPE]
一维数组是array[索引*TYPE]
汇编语言写的冒泡排序
二分查找