一、背景
如今大多数的大规模程序并非由汇编语言来编写,缘由很简单,由于太耗时了,可是汇编语言仍然被普遍运用在配置硬件设备以及优化程序的执行速度和尺寸大小等方面,特别是在逆向工程方面,更须要深刻理解与熟练掌握汇编语言。
针对现阶段,看汇编基本能看的明白,可是写起来须要查资料看语法的阶段,亟需多多练习汇编语言程序设计,夯实基础。结合早期学习C语言的经历,独立写一个冒泡排序的程序,从而促进汇编的掌握。
二、使用开发环境
代码编辑器:EmEditor
编译器:masm 6.0
调试工具:IDA 6.6web
三、编写思路与实现
由于编写的是排序功能过程,在windows下输入输出的编写不可以像C语言学习时使用printf函数打印结果那样直接,且为告终果输出可以更直观,因此选择windows32位编汇语言窗口程序的框架,在窗口消息处理函数中的PAINT消息中加入排序的功能函数,将传入的数组进行从新排序,后输出到windows窗口中。
本程序只是为了汇编程序的练习,至于算法中的优劣,以及汇编语言的效率并未考虑进去,有很大的多是效率不如C语言编写后的release版本,由于现阶段编译器的对高级语言的优化已经比较完善。再一点常见的状况是汇编代码都认识,可是组合到一块儿变得很难理解,除了是由于算法复杂的缘由,也有一部分缘由即是编译器的优化,把代码变得生涩。
3.1 C语言冒泡排序算法
void SortNum(int array[]; int length )
{
int i = 0;
int j = 0;
int tmp = 0;
for (i = 0; i < length; i++ ){
for (j = length - 1; j >= i + 1; j--){
if (array[j] < array[j - 1]){
tmp = array[j - 1];
array[j - 1] = array[j];
array[j] = tmp;
}
}
}
return;
}
算法比较简单,排序使用了for语句的双层循环,外层循环控制次数,共循环length次,内层循环将一个最小的值像气泡同样,一步步的排到最前面,外层循环第一次运行,则排出一个最小的,第二次,排出剩下的数中最小的,依次类推,则把剩下的数字从小到大排好。实际上外层循环用不上length次,只须要length-1次就能够了,可是此次代码只是作演示做用,不作深刻考究。算法
3.2 汇编语言for语句框架
汇编语言从正常的学习来讲,并无for语句框架这一律念,尽管MASM汇编中包含.WHILE、.REPEAT .WHILE等循环的伪指令,可是为了理解for语句在汇编中的运行机制,将其结构框架列出对于汇编的循环理解是颇有必要的。
for循环比while语句、 do while语句都要复杂,将其在C语言中的结构拆分,能够获得如下4步(对应C语言中的Debug版本):
①赋初值
②设置循环条件
③设置循环步长
④循环体代码编程
3.2 冒泡排序的汇编语言实现
数组的定义windows
.data
array DWORD 12, 8, -5, 7, 100 ;数组定义
arraryLength DWORD ($ - offset array) / sizeof(DWORD) ;数组长度
冒泡排序过程数组
_SortNum proc uses eax edx esi edi, pArray: PTR DWORD, dwArrayNum:DWORD
LOCAL @tmpNum:DWORD ; int tmp = 0
LOCAL @indexStep:DWORD ; int i = 0
LOCAL @indexNum:DWORD ; int j = 0
;外层循环进行第①步赋初值
mov @indexStep, 0 ;i = 0
jmp STEPCMPOUT
LOOPSTEPOUT:
;外层循环进行第③步设置循环步长
add @indexStep, 1 ;i++
STEPCMPOUT: ;外层循环进行第②步设置循环条件
mov eax, dwArrayNum ;i < length
cmp @indexStep, eax
jg RETURN ;若是外层循环结束,直接跳转到结束
mov eax, dwArrayNum ;设置内层循环第①步赋初值,也是
;外层循环的第④步循环体代码
dec eax ; length - 1
mov @indexNum, eax
jmp STEPCMPIN
LOOPSTEPIN: ;内层循环进行第③步设置循环步长
dec @indexNum ;j--
STEPCMPIN: ;内层循环进行第②步设置循环条件
mov eax, @indexStep ;j >= i + 1
inc eax
mov edx, @indexNum
cmp edx, eax
jl LOOPSTEPOUT ;若是内层循环完毕,则跳转到外层循环
; ③步设置循环步长
;内层循环第④步循环体代码
mov esi, pArray ;取出array[j]与array[j - 1]
mov edi, pArray
mov eax, @indexNum
mov edx, sizeof(DWORD)
mul edx
add esi, eax
sub eax, sizeof(DWORD)
add edi, eax
mov eax, [esi] ; if (array[j] < array[j - 1])
cmp eax, [edi]
jge LOOPSTEPIN ;若是array[j] < array[j - 1]
;不成立则跳转到设置循环步长操做
;若是如何上述的表达式,进行交换操做
mov eax, [edi] ; tmp = array[j - 1]
mov @tmpNum, eax
mov eax, [esi] ; array[j - 1] = array[j]
mov [edi], eax
mov eax, @tmpNum ; array[j] = tmp
mov [esi], eax
jmp LOOPSTEPIN ;内层循环循环体执行完毕进行跳转
jmp LOOPSTEPOUT ;外层循环循环体执行完毕进行跳转
RETURN:
ret
_SortNum endp
四、结束语
以上内容为冒泡排序的过程,可能值得完善的地方还有不少,起码对于array[j]与array[j - 1]值就未必是通用作法,可是参照此框架对于多层循环的for语句汇编实现,逆向多层for循环的代码,仍是有必定的实际意义。框架