zoukankan      html  css  js  c++  java
  • 汇编学习-分支与循环


    在高级语言程序设计中,我们不仅要求程序可以顺序运行,还要求其可以运行不同分支,或者反复运行某些操作。在汇编语言中,相同具有相同的能力,可以由对应的指令来控制程序的运行流程。由于毕竟高级语言都是汇编实现的,仅仅是不直观而已。

     

    转移

    无条件转移为JMP。类似c语言中的 goto

    c语言中,goto是不推荐使用的,会使程序难以控制和理解,但在汇编中,没有对应的if while语句。仅仅能使用 JMP来完毕逻辑复杂的控制结构。

    JMP分为段内转移和段间转移。只是在windows编程上,一个代码段的大小为 4GB。一般不须要段间转移。

     

    条件转移是由CPU提供多个标志位,在运行这类指令之前。检查之前已经设置的标志位的状态来决定是否进行转移。能够想象,通过条件转移。能够实现分支和循环。

     

    分支

    在汇编中,设计一个分支结构的思路基本是这种。由条件转移指令来推断条件是否满足,若满足,则跳过分支程序。否则继续向下运行,最后会合。

    x的符号

    c 程序

    </pre><pre name="code" class="cpp">int x = 10;
    int signX;
    int main()
    {
    	if (x > 0)
    		signX = 1;
    	else if (x == 0)
    		signX = 0;
    	else
    		signX = -1;
    }
    

    相应的汇编

    x                SDWORD        -45
    signX        SDWORD        ?
     
    mov signX, 0
    cmp        x, 0
    jz        a70                                ;为0
    jg        a60                                ;大于0
    mov signX, -1
    jmp        a70
    a60:
    mov        signX, 1
    a70:

     

    二分查找

    对于一个已排序的数组,最快的查找一个元素的方法不是顺序查找。而是二分查找。这个用c 语言写很方便。首先我们还是画出流程图,这有助于我们用 JMP转换之。

    数组为R,元素个数为n。要查找的数为a。

    运行过程为:
    1)先设定查找范围为下界 l到上界h

    2)假设下界大于上界,且没查到。则查找失败

    3)取下界和上界的中点m=(l+h)/2,该数为R[m]

    4)若该数为a,则算法结束

    5)若该数小于a。则改动下界l=m+1,并跳转到第二步

    6)若该数大于a,则改动上界 h=m-1,并跳转到第二步

    汇编源代码

    .386
    .model flat,stdcall        
    optioncasemap:none
    includelib  msvcrt.lib
    printf      PROTO C :dword, :vararg
     
    .data
    dArray      dword 50, 56, 64, 73, 83, 92, 103, 105
    ITEMS       equ    $-dArray)/4        ; 数组长度          
    Index           dword   ?
    Count           dword   ?
    szFmt           byte    'Index=%d Count=%d Element=%d', 0;  格式化字符串
    szErr           byte    'Not Found'
     
    l       sdword ?

    h sdword ? m sdword ? a sdword 83 ; 所查找的数字 .code start: mov Index, -1; mov Count, 0 mov l, 0 mov h, ITEMS-1; mov ecx, l mov edx, h b10: cmp ecx, edx ; 下界和上界比較 jg b40 ; 超出。则未找到 mov esi, ecx; add esi, edx shr esi, 1 ; m = (l+h)>>1 inc Count mov eax, a ; 取出被比較的数 cmp eax, dArray[esi*4] ; 取出该数 jz b30 ; 相等 jg b20 ; 比 a 小,改动下界 ; 比 a 大,改动上界 mov edx, esi dec edx ; h = m-1 jmp b10 b20: mov ecx, esi inc ecx ; l = m+1 jmp b10 b30: mov Index, esi ; 调用 c 库的 printf invoke printf, offset szFmt, Index, Count, dArray[esi*4] jmp b50 b40: ; 查找失败 invoke printf, offset szErr b50: ret end start


     

    有序表插入

    首先遍历数组。找到m,满足 R[m-1]<a && R[m]>a

    然后将R[m..n-1]每个元素向后移动一个位置,再插入a。

    关键部分汇编代码

    start:
        mov    eax, Element        ; 将插入的元素
        mov    esi, 0              ; 当前比較元素的下标
    c10:
        cmp    dArray[esi*4], eax
        ja     c20
        inc    esi
        cmp    esi, ITEMS          ; 超出数组长度,
        jb     c10                 ; 没有超出
        ;
    c20:
        mov    edi, ITEMS-1        ; 从数组尾部開始移动
    c30:
        cmp    edi, esi            ; 与插入位置比較
        jl     c40                 ; 移动完毕
        ; 还没完毕,继续移动
        mov    ebx, dArray[edi*4]
        mov    dArray[edi*4+4], ebx ; 向后移动一个元素
        dec    edi
        jmp    c30                 ; 继续推断。决定是否移动
    c40:
        mov    dArray[esi*4], eax  ; 移动完毕,插入元素


     

    循环

    实际编码解决这个问题时,常常遇到大量反复的动作,利用循环结构能够简化程序的编写。

    实际在上文中,已经有循环部分出现,但那是不定次数的循环。

    一个循环结构分为三部分:循环初始化,循环体,循环结束控制。

    一个固定次数的循环,有LOOP命令来实现。循环次数在ECX中。

     

    阶乘

    这里直接使用ECX 作为乘数。其会随循环递减。正好符合阶乘的定义。

    .data
        Fact   dword   ?
        N      EQU     5
    .code
    start:
        mov    ecx, N      ; 循环初值,同一时候也是乘数初值
        mov    eax, 1      ; fact 初值
    e10:
        imul   eax, ecx    ; 相乘
        loop   e10
       
        mov    Fact, eax   ; 阶乘结果


     

    冒泡

    冒泡算法是一个多重循环。

    start:
        mov    ecx, ITEMS-1
    i10:
        xor    esi, esi    ; 清零
    i20:
        mov    eax, dArray[esi*4]
        mov    ebx, dArray[esi*4+4]
        cmp    eax, ebx    ; 比較相邻的两个数
        jl     i30
        mov    dArray[esi*4], ebx    ;较大的数在左边。须要移动
        mov    dArray[esi*4+4], eax  ; 须要交换两个数
    ; 比較下一对数
    i30:
        inc    esi
        cmp    esi, ecx
        jb     i20     ; 内循环。一遍下来,最大的数,移到了最右边
        loop   i10     ; 外循环

    參考文献

    [1] 谭毓安, 张雪兰. Windows汇编语言程序设计教程. 北京: 电子工业出版社, 2005.

  • 相关阅读:
    正则表达式替换所有符合条件的字符
    关于jquery ajax不执行success回调函数
    关于jquery绑定事件执行两次
    同步选中所有checkbox
    Jquery动态改变my97datepicker的日期形式
    关于button在td中时,zclip复制不能的问题
    关于各种高度的获取方法
    慎用--skip-grant-tables命令
    Mysql中判断是否存在
    前端html
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/6718176.html
Copyright © 2011-2022 走看看