• 学 Win32 汇编[15]: LOOP 与标号



    Loop 是反复执行;
    从哪反复? 这要用到 "标号";
    反复几次? 把反复的次数告诉 ECX 寄存器即可.

    笨办法计算 3 * 8 = 24
    ; Test15_1.asm
    .386
    .model flat, stdcall
    
    include    windows.inc
    include    kernel32.inc
    include    masm32.inc
    include    debug.inc
    includelib kernel32.lib
    includelib masm32.lib
    includelib debug.lib
    
    .data
        val dd 3
    .code
    main proc
        xor eax, eax
        add eax, val
        add eax, val
        add eax, val
        add eax, val
        add eax, val
        add eax, val
        add eax, val
        add eax, val
        PrintDec eax  ;24
        ret
    main endp
    end main
    

    使用 LOOP 和标号:
    ; Test15_2.asm
    .386
    .model flat, stdcall
    
    include    windows.inc
    include    kernel32.inc
    include    masm32.inc
    include    debug.inc
    includelib kernel32.lib
    includelib masm32.lib
    includelib debug.lib
    
    .data
        val dd 3
    .code
    main proc
        xor eax, eax
        mov ecx, 8
    L1:               ;命名为 "L1" 的标号
        add eax, val
        loop L1       ;反复到指定标号; 每次反复 ecx 会减 1, 直到 ecx 为 0 才向下执行
    
        PrintDec eax  ;24
        ret
    main endp
    end main
    

    数组求和的例子:
    ; Test15_3.asm
    .386
    .model flat,  stdcall
    
    include    windows.inc
    include    kernel32.inc
    include    masm32.inc
    include    debug.inc
    includelib kernel32.lib
    includelib masm32.lib
    includelib debug.lib
        
    .data
        dwArr dd 1,2,3,4,5
    .code
    main proc
        lea edi, dwArr           ;把数组起始地址给一个寄存器
        mov ecx, lengthof dwArr  ;把数组元素数(将要反复的次数)给 ECX
        xor eax, eax
    L1:
        add  eax, [edi]          ;edi 中的地址将不断变化, 通过 [edi] 获取元素值
        add  edi, type dwArr     ;获取下一个元素的地址
        loop L1
        
        PrintDec eax  ;15
        ret
    main endp
    end main
    

    复制字符串的例子:
    ; Test15_4.asm
    .386
    .model flat, stdcall
    
    include    windows.inc
    include    kernel32.inc
    include    masm32.inc
    include    debug.inc
    includelib kernel32.lib
    includelib masm32.lib
    includelib debug.lib
        
    .data
        szSource db 'Hello World!', 0       ;定义源字符串
        szDest   db sizeof szSource dup(0)  ;定义相同大小的目的字符串
    .code
    main proc
        mov  esi, 0                ;这里选择使用 esi 做数组索引
        mov  ecx, sizeof szSource  ;这是要循环的次数
    L1:
        mov  al, szSource[esi]     ;mov 的操作数不允许两个都是变量, 用 al 中转一下
        mov  szDest[esi], al       ;
        inc  esi                   ;调整索引
        loop L1
        
        PrintString szDest         ;Hello World!
        ret
    main endp
    end main
    

    如果仅仅是复制字符串, 可以使用声明在 masm32.inc 中的 szCopy 函数:
    ; Test15_5.asm
    .386
    .model flat, stdcall
    
    include    windows.inc
    include    kernel32.inc
    include    masm32.inc
    include    debug.inc
    includelib kernel32.lib
    includelib masm32.lib
    includelib debug.lib
        
    .data
        szSource db 'Hello World!', 0
        szDest   db sizeof szSource dup(0)
    .code
    main proc
        invoke szCopy, addr szSource, addr szDest
        PrintString szDest  ;Hello World!
        ret
    main endp
    end main
    

    关于 @@、@B、@F:
    
    ; 如果懒得给标号取名, 可以使用 @@ 做标号;
    ; @B 表示前面最近的一个标号、@F 表示后面最近的一个标号;
    ; 使用 @@ 可以把前面 3*8=24 的例子修改如下:
    
    ; Test15_6.asm
    .386
    .model flat, stdcall
    
    include    windows.inc
    include    kernel32.inc
    include    masm32.inc
    include    debug.inc
    includelib kernel32.lib
    includelib masm32.lib
    includelib debug.lib
    
    .data
        val dd 3
    .code
    main proc
        xor eax, eax
        mov ecx, 8
    @@:
        add eax, val
        loop @B
        PrintDec eax  ;24
        ret
    main endp
    end main
    

    关于全局标号:
    
    ; 上面例子中的标号都是局部标号;
    ; 如果一个标号定义在子过程之外, 那它就是全局标号了.
    ; 能不能在子过程中定义全局标号呢? 后面加两个 : 就是了.
    
    ; Test15_7.asm
    .386
    .model flat, stdcall
    
    include    windows.inc
    include    kernel32.inc
    include    masm32.inc
    include    debug.inc
    includelib kernel32.lib
    includelib masm32.lib
    includelib debug.lib
    
    .data
        val dd 3
    .code
    
    MyProc proc
    Label1::               ;是 Label1:: 而不是 Label1:
        PrintText 'MyProc'
        ret
    MyProc endp
    
    main proc
        PrintText 'main'
        jmp Label1  ;jmp 是无条件跳转指令
        ret
    main endp
    end main
    

  • 相关阅读:
    Java annotation
    子类 父类强转 HttpServlet service实现
    父类 子类 强转
    HttpServlet Service方法
    java go
    IO写 PrintWriter
    IO读 BufferedReader+FileReader
    Java NIO-3
    心跳包(HeartBeat)
    Git学习笔记(一)
  • 原文地址:https://www.cnblogs.com/del/p/1707543.html
Copyright © 2020-2023  润新知