zoukankan      html  css  js  c++  java
  • 《汇编语言 基于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
  • 相关阅读:
    深入理解java异常处理机制
    i2c总线
    运行时类型识别(RTTI)
    bcg界面库总结
    c++ 虚函数表
    宽字符,宽字符串
    c++异常处理
    内存管理
    c++中使用联合体
    MFC自定义消息
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9648847.html
Copyright © 2011-2022 走看看