zoukankan      html  css  js  c++  java
  • 《汇编语言 基于x86处理器》前五章的小程序

    ▶ 书中前五章的几个小程序,基本的运算操作,使用了作者的库 Irvine32 和 Irvine64(一开始以为作者网站过期了,各网站上找到的文件大小都不一样,最后发现是要搭梯子 Orz,顺利下载)。注意编译前将相关的库文件放到 “项目属性 → 链接器 → 输入 → 附加依赖项” 中。

    ● 代码,整数数组求和

     1 .386
     2 .model flat,stdcall
     3 .stack 4096
     4 
     5 ExitProcess PROTO, dwExitCode: dword
     6 
     7 .data
     8     array DWORD 10000h, 20000h, 30000h, 40000h,
     9 
    10 .code
    11 main PROC
    12     mov edi, OFFSET array   ; 变址寄存器获得 array 首元素地址
    13     mov ecx, LENGTH array   ; 循环计数器获得 array 元素个数
    14     mov eax, 0
    15 
    16 L1:
    17     add eax, [edi]          ; 将 array 每个元素加到 eax 中
    18     add edi, TYPE array     ; 递增变址寄存器
    19     loop L1                 ; 循环直到 ecx 减为 0
    20 
    21     INVOKE ExitProcess, 0
    22 main ENDP
    23 
    24 END main

    ● 代码,整数数组求和,64位版本

     1 ExitProcess PROTO
     2 
     3 .data
     4     array QWORD 1000000000000h, 2000000000000h, 3000000000000h, 4000000000000h,
     5 
     6 .code
     7 main PROC
     8     mov rdi, OFFSET array   ; 用到的寄存器都改成 64 位的版本
     9     mov rcx, LENGTH array
    10     mov rax, 0
    11 
    12 L1:
    13     add rax, [rdi]
    14     add rdi, TYPE array
    15     loop L1
    16 
    17     mov ecx, 0              ; 还是使用 ecx 作为返回值
    18     call ExitProcess
    19 main ENDP
    20 
    21 END

    ● 代码,复制字符串

     1 .386
     2 .model flat,stdcall
     3 .stack 4096
     4 
     5 ExitProcess PROTO, dwExitCode: dword
     6 
     7 .data
     8     source BYTE "Something to be copied 2333.",0
     9     target BYTE SIZEOF source DUP(0)
    10 
    11 .code
    12 main PROC
    13     mov esi, OFFSET source
    14     mov ecx, LENGTH source
    15 
    16 L1:
    17     mov al, source[esi]
    18     mov target[esi], al
    19     inc esi
    20     loop L1
    21 
    22     INVOKE ExitProcess, 0
    23 main ENDP
    24 
    25 END main

    ● 涨姿势,代码中间有一个块段注释没有封口(直到代码结尾都是注释),报错信息是 END directive required at end of file。

    ● 代码,翻转字符串

     1 .386
     2 .model flat,stdcall
     3 .stack 4096
     4 
     5 ExitProcess PROTO, dwExitCode: dword
     6 
     7 .data
     8     source BYTE "Something to be copied 2333.", 0
     9     nameSize = ($ - source) - 1 ; 使用常量来存储字符串的长度
    10 
    11 .code
    12 main PROC
    13     mov esi, 0
    14     mov ecx, LENGTH source
    15 
    16 L1:
    17     movzx eax, source[esi]      ; 获取字符,压栈,递增指针,循环
    18     push eax
    19     inc esi
    20     loop L1
    21 
    22     mov esi, 0                  ; 相同的赋值
    23     mov ecx, LENGTH source
    24 L2:
    25     pop eax                     ; 吐栈,放入字符,递增指针,循环
    26     mov source[esi], eax
    27     inc esi
    28     loop L2
    29 
    30     INVOKE ExitProcess, 0
    31 main ENDP
    32 
    33 END main

    ● 代码,使用子过程计算数组的和

     1 .386
     2 .model flat,stdcall
     3 .stack 4096
     4 ExitProcess proto,dwExitCode:dword
     5 
     6 .data
     7     array dword 10000h,20000h,30000h,40000h,50000h
     8     sum   dword ?
     9 
    10 .code
    11 sumArray proc uses esi ecx  ; 定义子过程,uses 在栈中备份 esi 和 ecx,并在 ret 前还原
    12     ;push esi                ; 用栈备份用到的寄存器,与 uses 作用等效
    13     ;push ecx
    14     mov eax, 0
    15 
    16 L1:                         ; 使用循环将和放入 eax 中
    17     add eax, [esi]
    18     add esi, type dword
    19     loop L1
    20 
    21     ;pop ecx                 ; 从栈中还原寄存器的状态
    22     ;pop esi
    23     ret                     ; 从子过程中返回
    24 sumArray endp
    25 
    26 main proc    
    27     mov esi, offset array
    28     mov ecx, length array
    29 
    30     call sumArray
    31     mov sum, eax
    32     
    33     invoke ExitProcess, 0
    34 main endp
    35 
    36 end main

    ● 代码,库 Irvine32 测试 1,简单的输入输出。记得在 “属性,配置属性,链接器,输入” 中加上 Irvine32.lib,并在工作目录下添加 Irvine32.inc,Irvine32.lib,SmallWin.inc,VirtualKeys.inc。

     1 INCLUDE Irvine32.inc                    ; 包含库
     2 .data
     3 array     DWORD 1000h,2000h,3000h
     4 message    BYTE "Enter a 32-bit signed integer: ", 0
     5 dwordVal   DWORD ?
     6 
     7 .code
     8 main PROC
     9     mov     eax,    yellow + (blue * 16)
    10     call    SetTextColor
    11     call    Clrscr                      ; 清屏为背景色
    12     call    DumpRegs                    ; 显示当亲寄存器状态
    13 
    14     mov     esi,    OFFSET array        ; 三个寄存器分别存储数组的信息
    15     mov     ecx,    LENGTHOF array    
    16     mov     ebx,    TYPE array    
    17     call    DumpMem                     ; 调用库函数,输出数组所有元素
    18     call    Crlf                        ; 换行
    19 
    20     mov     edx,    OFFSET message
    21     call    WriteString                 ; 输出字符串
    22     call    ReadInt                     ; 输入整数
    23     mov     dwordVal,   eax             ; 输入的整数存储到 eax 中
    24     call    Crlf            
    25     call    WriteInt                    ; 用十进制、十六进制、二进制输出 eax
    26     call    Crlf
    27     call    WriteHex        
    28     call    Crlf
    29     call    WriteBin        
    30     call    Crlf    
    31     call    WaitMsg                     ; 显示 "Press any key to cintinue" 并等待
    32 
    33     mov     eax,    lightGray + (black * 16)    ; 恢复终端颜色
    34     call    SetTextColor
    35     call    Clrscr
    36     call    WaitMsg
    37     
    38     exit
    39 main ENDP
    40 END main

    ● 输出结果

    ; 清屏为蓝色
    
      EAX=0000001E  EBX=00436000  ECX=00961055  EDX=00961055
      ESI=00961055  EDI=00961055  EBP=0075FE18  ESP=0075FE08
      EIP=00963674  EFL=00000202  CF=0  SF=0  ZF=0  OF=0  AF=0  PF=0
    
    
    Dump of offset 00966000
    -------------------------------
    00001000  00002000  00003000
    
    Enter a 32-bit signed integer: 65536    ; 输入
    
    +65536
    00010000
    0000 0000 0000 0001 0000 0000 0000 0000
    Press any key to continue...
    
    ; 清屏恢复黑色
    
    Press any key to continue...

    ● 代码,库 Irvine32 测试 2,随机数

     1 INCLUDE Irvine32.inc
     2 
     3 TAB = 9        ; ASCII code for Tab
     4 
     5 .code
     6 main PROC
     7     call    Randomize   ; 随机数种子
     8     call    Rand1       ; 无符号随机数
     9     call    Rand2       ; 有符号随机数
    10     call    WaitMsg
    11     exit
    12 main ENDP
    13 
    14 Rand1 PROC
    15     mov    ecx, 10
    16 L1:
    17     call    Random32    ; 生成随机整数用于输出
    18     call    WriteDec
    19     mov     al, TAB     ; 给一个水平制表符用于输出
    20     call    WriteChar
    21     loop    L1
    22 
    23     call    Crlf
    24     ret
    25 Rand1 ENDP
    26 
    27 Rand2 PROC
    28     mov    ecx, 10
    29 
    30 L1:
    31     mov     eax, 100
    32     call    RandomRange ; 生成给定范围内的随机数
    33     sub     eax, 50
    34     call    WriteInt
    35     mov     al,TAB
    36     call    WriteChar
    37     loop    L1
    38 
    39     call    Crlf
    40     ret
    41 Rand2 ENDP
    42 
    43 END main

    ● 代码,库 Irvine32 测试 3,计时器

     1 INCLUDE Irvine32.inc
     2 
     3 .data
     4 OUTER_LOOP_COUNT = 3
     5 startTime DWORD ?
     6 msg1 BYTE "Start", 0dh, 0ah, 0          ; 等价于 "Start
    "
     7 msg2 BYTE "End", 0dh, 0ah, "Time(ms): ", 0
     8 
     9 .code
    10 main PROC
    11     mov     edx,    OFFSET msg1
    12     call    WriteString
    13 
    14     call    GetMSeconds                 ; 计时器1
    15     mov     startTime,  eax
    16 
    17     mov     ecx,    OUTER_LOOP_COUNT    ; 外层循环
    18 L1:    
    19     call    innerLoop
    20     loop    L1
    21 
    22     call    GetMSeconds                 ; 计时器2
    23     sub     eax,    startTime           ; 直接在 eax 中计算耗时
    24         
    25     mov     edx,    OFFSET msg2         ; 显示
    26     call    WriteString
    27     call    WriteDec
    28     call    Crlf
    29     
    30     call WaitMsg
    31     exit
    32 main ENDP
    33 
    34 innerLoop PROC uses ecx             
    35     mov     ecx,    0FFFFFFFh           ; 内层循环
    36 L1:
    37     mul     eax                         ; 无符号乘法
    38     mul     eax
    39     mul     eax
    40     loop    L1
    41         
    42     ret
    43 innerLoop ENDP
    44 
    45 END main

    ● 代码,库 Irvine32 测试 4,对话框

     1 INCLUDE Irvine32.inc
     2 
     3 .data
     4 caption db "Title", 0
     5 HelloMsg    BYTE "This is a pop-up message box.", 0dh, 0ah, 0
     6 
     7 .code
     8 main PROC   
     9     mov    ebx, OFFSET caption  ; 标题,可以为 0
    10     mov    edx, OFFSET HelloMsg ; 对话框内容
    11     call    MsgBox
    12 
    13     mov ebx,    OFFSET caption
    14     mov edx,    OFFSET HelloMsg
    15     call MsgBoxAsk              ; 返回值在 eax 中,6(yes) 或 7(no)
    16 
    17     call    WaitMsg
    18     exit
    19 main ENDP
    20 
    21 END main 

    ● 代码,库 Irvine32 测试 5,用不同编码输出编号为 1~255 的字符

     1 INCLUDE Irvine32.inc
     2 
     3 SetConsoleOutputCP PROTO, pageNum:DWORD
     4 
     5 .data
     6 divider     BYTE    " - ", 0
     7 codepage    DWORD   1252
     8     ; 1250 - Central Europe
     9     ; 1251 - Cyrillic
    10     ; 1252 - Latin I
    11     ; 1253 - Greek
    12     ; 1254 - Turkish
    13     ; 1255 - Hebrew
    14     ; 1256 - Arabic
    15     ; 1247 - Baltic
    16     ; 1258 - Vietnam
    17     ; 874  - Thai
    18     ; 437  - OEM United States
    19     ; 858  - OEM Multilingual Latin and European
    20 
    21 .code
    22 main PROC
    23     invoke SetConsoleOutputCP, codePage
    24 
    25     mov     ecx,    255
    26     mov     eax,    1
    27     mov     edx,    OFFSET divider
    28 L1:    
    29     call    WriteDec    ; eax 作为计数器
    30     call    WriteString ; edx 指向字符串
    31     call    WriteChar   ; al 为得到的字符
    32     call    Crlf
    33     inc     aL
    34     Loop    L1
    35 
    36     call    WaitMsg
    37     exit
    38 main ENDP
    39 
    40 END main

    ● 代码,库 Irvine64 测试 1,显示 20 个 64 位随机数

     1 ExitProcess PROTO           ; 手动声明需要用到的函数
     2 WriteInt64  PROTO
     3 Crlf        PROTO
     4 Random64    PROTO
     5 RandomRange PROTO
     6 Randomize   PROTO
     7 
     8 .code
     9 main proc
    10     sub     rsp,    8       ; 栈指针对其到 16 Byte
    11     sub     rsp,    20h     ; 影子空间 32 Byte
    12 
    13     call  Randomize
    14     mov     rcx,    20
    15 L1:
    16     mov     rax,    234324243242
    17     call    RandomRange     ; 返回的 64 位随机数在 eax 中
    18     call    WriteInt64
    19     call    Crlf
    20     loop    L1
    21 
    22     add  rsp,   28h         ; 恢复 rsp 指针位置,main 中可以不用,子过程中需要
    23     mov  ecx,   0
    24     call ExitProcess
    25 main endp
    26 
    27 end

    ● 涨姿势,链接时把 irvine64.obj 加入项目中(添加现有项),然后报错 LNK2017 没有 /LARGEADDRESSAWARE:NO,“ADDR32”到“bufferLHB”的重定位无效 。改正:“属性,配置属性,连接器,系统,启用大地址” 选否(/LARGEADDRESSAWARE:NO),即可正确运行。

     ● 代码,库 Irvine64 测试 2,简单的输入输出

     1 ExitProcess     proto
     2 ReadInt64       proto
     3 ReadString      proto
     4 WriteString     proto
     5 WriteInt64      proto
     6 WriteHex32      proto
     7 WriteHex64      proto
     8 Crlf            proto
     9 
    10 .data
    11 message BYTE "Test irvine64.lib", 0
    12 maxval qword 9223372036854775807
    13 minval qword -9223372036854775808
    14 inbuf  BYTE  50 dup(0),0
    15 inbuf_size = $ - inbuf
    16 
    17 .code
    18 main proc
    19 
    20     mov     rdx,offset message
    21     call    WriteString
    22     call    Crlf
    23 
    24     call    ReadInt64       ; 从键盘读取一个 64 位整数
    25     call    Crlf
    26     call    WriteInt64
    27     call    Crlf
    28     
    29     mov     rdx,offset inbuf
    30     call    WriteString
    31     call    Crlf
    32 
    33     mov     rax,    minVal
    34     call    WriteInt64
    35     call    Crlf
    36 
    37     mov     rax,    maxVal
    38     call    WriteInt64
    39     call    Crlf
    40 
    41     mov   ecx, 0
    42     call  ExitProcess
    43 main endp
    44 
    45 end
  • 相关阅读:
    Nokia Qt SDK开发环境使用
    iPad不久将能使用Android系统
    原生IDE新军:JRuby阵营的RedCar,JavaScript阵营的Cloud9(自己写个IDE出来一定很复杂吧)
    手机产品的信息架构
    百万开发者拥戴!七大.NET著名开源项目
    Prism 4.0发布最终版,支持Windows Phone 7
    Qt Symbian 开发环境安装
    Qt 4.7.1 和 Mobility 1.1.0 已发布
    WSI闭关,这对WS*意味着什么?(个人觉得Web Services是个好东西)
    ERROR: unknown virtual device name解决方法
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9571648.html
Copyright © 2011-2022 走看看