▶ 书中第九章的程序,主要讲了字符串相关的输入、输出,以及冒泡排序、二分搜索
● 代码,Irvine32 中的字符串库函数代码范例
1 INCLUDE Irvine32.inc 2 3 .data 4 str1 BYTE "abcde////", 0 5 str2 BYTE "ABCDE", 0 6 msg0 BYTE "Upper case: ", 0 7 msg1 BYTE "str1 == str2", 0 8 msg2 BYTE "str1 < str2", 0 9 msg3 BYTE "str1 > str2", 0 10 msg4 BYTE "Length of str1: ", 0 11 msg5 BYTE "Trimming: ", 0 12 13 .code 14 main PROC 15 mov edx, OFFSET str1 16 call WriteString 17 call crlf 18 19 call trim_string 20 call upper_case 21 call compare_strings 22 call print_length 23 call waitmsg 24 exit 25 main ENDP 26 27 trim_string PROC ; 去掉结尾的指定字符 28 INVOKE Str_trim, ADDR str1, '/' 29 mov edx, OFFSET msg5 30 call WriteString 31 mov edx, OFFSET str1 32 call WriteString 33 call Crlf 34 ret 35 trim_string ENDP 36 37 upper_case PROC ; 小写转大写 38 mov edx, OFFSET msg0 39 call WriteString 40 INVOKE Str_ucase, ADDR str1 41 mov edx, OFFSET str1 42 call WriteString 43 call Crlf 44 ret 45 upper_case ENDP 46 47 compare_strings PROC ; 比较 str1 和 str2 48 INVOKE Str_compare, ADDR str1, ADDR str2 49 .IF ZERO? 50 mov edx, OFFSET msg1 ; str1 = str2 51 .ELSEIF CARRY? 52 mov edx, OFFSET msg2 ; str1 < str2 53 .ELSE 54 mov edx, OFFSET msg3 ; str1 > str2 55 .ENDIF 56 call WriteString 57 call Crlf 58 ret 59 compare_strings ENDP 60 61 print_length PROC ; 获取字符串长度 62 mov edx, OFFSET msg4 63 call WriteString 64 INVOKE Str_length, ADDR str1 65 call WriteDec 66 call Crlf 67 ret 68 print_length ENDP 69 70 END main
■ 输出结果
abcde//// Trimming: abcde Upper case: ABCDE str1 == str2 Length of str1: 5
● 用宏来计算矩阵某一行的元素的和
1 INCLUDE Irvine32.inc 2 3 mCalc_row_sum MACRO index, arrayOffset, rowSize, eltType 4 LOCAL L1 ; 指定局部循环点 5 push ebx 6 push ecx 7 push esi 8 9 mov eax, index 10 mov ebx, arrayOffset 11 mov ecx, rowSize 12 13 mul ecx ; eax = 选取行的行偏移 14 add ebx, eax ; ebx = 选取行的首元素地址 15 shr ecx, (TYPE eltType / 2) ; 控制循环次数 byte=0, word=1, dword=2 16 ; 因为循环内数组寻址使用 esi 完成的,ecx 要单独计算 17 mov eax, 0 ; 存放和 18 mov esi, 0 ; 列下标 19 20 L1: 21 IFIDNI <eltType>, <DWORD> ; DWORD 使用的寄存器不一样,区别对待 22 mov edx, eltType PTR[ebx + esi*(TYPE eltType)] 23 ELSE 24 movzx edx, eltType PTR[ebx + esi*(TYPE eltType)] 25 ENDIF 26 27 add eax, edx 28 inc esi 29 loop L1 30 31 pop esi 32 pop ecx 33 pop ebx 34 ENDM 35 36 .data 37 tableB BYTE 10h, 20h, 30h, 40h, 50h 38 RowSizeB = ($ - tableB) ; 数组定义断开,中间插入一个用于计算数组行宽的常量 39 BYTE 60h, 70h, 80h, 90h, 0A0h 40 BYTE 0B0h, 0C0h, 0D0h, 0E0h, 0F0h 41 42 tableW WORD 10h, 20h, 30h, 40h, 50h 43 RowSizeW = ($ - tableW) 44 WORD 60h, 70h, 80h, 90h, 0A0h 45 WORD 0B0h, 0C0h, 0D0h, 0E0h, 0F0h 46 47 tableD DWORD 10h, 20h, 30h, 40h, 50h 48 RowSizeD = ($ - tableD) 49 DWORD 60h, 70h, 80h, 90h, 0A0h 50 DWORD 0B0h, 0C0h, 0D0h, 0E0h, 0F0h 51 52 index DWORD 1 ; 指定要计算的行号 53 54 .code 55 main PROC 56 mCalc_row_sum index, OFFSET tableB, RowSizeB, BYTE 57 call WriteHex 58 call Crlf 59 60 mCalc_row_sum index, OFFSET tableW, RowSizeW, WORD 61 call WriteHex 62 call Crlf 63 64 mCalc_row_sum index, OFFSET tableD, RowSizeD, DWORD 65 call WriteHex 66 call Crlf 67 68 call WaitMsg 69 exit 70 main ENDP 71 72 END main
● 64 位版本,主要区别就是函数声明,使用的寄存器
1 ExitProcess PROT 2 WriteHex64 PROTO 3 Crlf PROTO 4 5 mCalc_row_sum MACRO index, arrayOffset, rowSize, eltType 6 LOCAL L1 7 push rbx 8 push rcx 9 push rsi 10 11 mov rax, index 12 mov rbx, arrayOffset 13 mov rcx, rowSize 14 15 16 mul rcx 17 add rbx, rax 18 shr rcx, (TYPE eltType / 2) 19 20 mov rax, 0 21 mov rsi, 0 22 23 L1: 24 IFIDNI <eltType>, <DWORD> 25 mov edx,eltType PTR[rbx + rsi*(TYPE eltType)] 26 ELSE 27 movzx edx,eltType PTR[rbx + rsi*(TYPE eltType)] 28 ENDIF 29 30 add rax, rdx 31 inc rsi 32 loop L1 33 34 pop rsi 35 pop rcx 36 pop rbx 37 ENDM 38 39 .data 40 tableB BYTE 10h, 20h, 30h, 40h, 50h 41 RowSizeB = ($ - tableB) 42 BYTE 60h, 70h, 80h, 90h, 0A0h 43 BYTE 0B0h, 0C0h, 0D0h, 0E0h, 0F0h 44 45 tableW WORD 10h, 20h, 30h, 40h, 50h 46 RowSizeW = ($ - tableW) 47 WORD 60h, 70h, 80h, 90h, 0A0h 48 WORD 0B0h, 0C0h, 0D0h, 0E0h, 0F0h 49 50 tableD DWORD 10h, 20h, 30h, 40h, 50h 51 RowSizeD = ($ - tableD) 52 DWORD 60h, 70h, 80h, 90h, 0A0h 53 DWORD 0B0h, 0C0h, 0D0h, 0E0h, 0F0h 54 55 index QWORD 1 56 57 58 .code 59 main PROC 60 mCalc_row_sum index, OFFSET tableB, RowSizeB, BYTE 61 call WriteHex64 62 call Crlf 63 64 mCalc_row_sum index, OFFSET tableW, RowSizeW, WORD 65 call WriteHex64 66 call Crlf 67 68 mCalc_row_sum index, OFFSET tableD, RowSizeD, DWORD 69 call WriteHex64 70 call Crlf 71 72 mov ecx, 0 73 call ExitProcess 74 main ENDP 75 76 END
● 代码,冒泡排序,二分搜索
1 ; BinarySearchTest.asm,测试函数 2 INCLUDE Irvine32.inc 3 INCLUDE BinarySearch.inc 4 5 LOWVAL = -5000 6 HIGHVAL = +5000 7 ARRAY_SIZE = 50 8 9 .data 10 array DWORD ARRAY_SIZE DUP(?) 11 12 .code 13 main PROC 14 call Randomize ; 初始化随机数种子 15 INVOKE FillArray, ADDR array, ARRAY_SIZE, LOWVAL, HIGHVAL ; 用随机数填充数组 16 INVOKE PrintArray, ADDR array, ARRAY_SIZE ; 显示数组内容 17 call WaitMsg 18 call Crlf 19 20 INVOKE BubbleSort, ADDR array, ARRAY_SIZE ; 冒泡排序 21 INVOKE PrintArray, ADDR array, ARRAY_SIZE 22 call WaitMsg 23 call Crlf 24 25 call AskForSearchVal ; 输入待查找的数字 26 INVOKE BinarySearch, ADDR array, ARRAY_SIZE, eax ; 二叉搜索 27 call ShowResults ; 输出搜索结果 28 call WaitMsg 29 30 exit 31 main ENDP 32 33 AskForSearchVal PROC 34 .data 35 prompt BYTE "Signed integer to find: ",0 36 .code 37 call Crlf 38 mov edx, OFFSET prompt 39 call WriteString 40 call ReadInt 41 ret 42 AskForSearchVal ENDP 43 44 ShowResults PROC 45 .data 46 msg1 BYTE "Not found.",0 47 msg2 BYTE "Found at index:",0 48 .code 49 .IF eax == -1 50 mov edx, OFFSET msg1 51 call WriteString 52 .ELSE 53 mov edx, OFFSET msg2 54 call WriteString 55 call WriteDec 56 .ENDIF 57 call Crlf 58 ret 59 ShowResults ENDP 60 61 END main
1 ; FillArray.asm,用 [LowerRange, UpperRange - 1] 之间随机的整数来填充数组 2 INCLUDE Irvine32.inc 3 4 .code 5 FillArray PROC USES eax edi ecx edx, pArray:PTR DWORD, Count:DWORD, LowerRange:SDWORD, UpperRange:SDWORD 6 7 mov edi, pArray 8 mov ecx, Count 9 mov edx, UpperRange 10 sub edx, LowerRange 11 cld ; 清除方向标志位 12 13 L1: 14 mov eax, edx 15 call RandomRange 16 add eax, LowerRange 17 stosd ; eax 的值保存到 [edi] 18 loop L1 19 20 ret 21 FillArray ENDP 22 23 END
1 ; PrintArray.asm,打印数组 2 INCLUDE Irvine32.inc 3 4 .code 5 PrintArray PROC USES eax ecx edx esi, pArray:PTR DWORD, Count:DWORD 6 7 .data 8 comma BYTE ", ",0 ; 逗号 9 .code 10 mov esi, pArray 11 mov ecx, Count 12 cld 13 14 L1: 15 lodsd ; 读取 [ESI] 给 eax 16 call WriteInt 17 mov edx, OFFSET comma 18 call Writestring 19 loop L1 20 21 call Crlf 22 ret 23 PrintArray ENDP 24 25 END
1 ; BubbleSort.asm,冒泡排序 2 INCLUDE Irvine32.inc 3 4 .code 5 BubbleSort PROC USES eax ecx esi, pArray:PTR DWORD, Count:DWORD 6 7 mov ecx, Count 8 dec ecx ; 外层循环 ecx -->0 9 10 L1: 11 push ecx ; 内层循环,保存 ecx 12 mov esi, pArray 13 14 L2: 15 mov eax, [esi] ; 取出相邻两个元素作比较 16 cmp [esi + 4] ,eax 17 jge L3 ; pArray[esi] < pArray[esi + 1] 跳转,不发生交换 18 xchg eax, [esi+4] 19 mov [esi], eax 20 21 L3: 22 add esi, 4 ; 后移一位 23 loop L2 24 25 pop ecx ; 退到外层循环以前恢复 ecx 26 loop L1 27 28 L4: 29 ret 30 BubbleSort ENDP 31 32 END
1 ; BinarySearch.asm,二分搜索 2 INCLUDE Irvine32.inc 3 4 .code 5 BinarySearch PROC USES ebx edx esi edi, pArray:PTR DWORD, Count:DWORD, searchVal:DWORD 6 7 LOCAL first:DWORD, last:DWORD, mid:DWORD 8 9 mov first, 0 10 mov eax, Count 11 dec eax 12 mov last, eax 13 mov edi, searchVal 14 mov ebx, pArray 15 16 L1: ; first <= last 17 mov eax, first 18 cmp eax, last 19 jg L5 ; first > last,退出搜索 20 21 mov eax, last ; 计算 mid 22 add eax, first 23 shr eax, 1 24 mov mid, eax 25 26 mov esi, mid 27 shl esi, 2 ; 下标乘以 4,变成数组偏移量 28 mov edx, [ebx + esi] ; EDX = pArray[mid] 29 30 cmp edx, edi ; 比较 edx 和 查找的值 31 jge L2 ; edx >= searchval 跳转 32 mov eax, mid ; first = mid + 1 33 inc eax 34 mov first, eax 35 jmp L4 36 37 L2: 38 cmp edx,edi ; 比较 edx 和 查找的值 39 jle L3 ; edx <= searchval 跳转 40 mov eax, mid ; last = mid - 1 41 dec eax 42 mov last, eax 43 jmp L4 44 45 L3: 46 mov eax, mid ; edx == searchval 47 jmp L9 ; 返回,eax即为找到的下标 48 49 L4: 50 jmp L1 ; 调整过 first 或 last,继续搜索 51 52 L5: 53 mov eax, -1 ; 没找到 54 L9: 55 ret 56 BinarySearch ENDP 57 58 END