《汇编语言 基于x86处理器》第九章字符串与数组部分的代码

▶ 书中第九章的程序,主要讲了字符串相关的输入、输出,以及冒泡排序、二分搜索

● 代码,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
原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9648847.html