简介

掌握汇编语言程序设计方法

  • 顺序程序结构
  • 分支程序结构
  • 循环程序结构
    重点
  • 控制转移指令
  • 转移指令的寻址方式

编制汇编语言程序的步骤

分析问题,确定算法

  • 找出合理的算法及适当的数据结构

根据算法画出程序框图

  • 由粗到细把算法逐步地具体化

根据框图编写源程序
上机调试

1.顺序程序结构

无分支、无循环、无转移,按照 程序书写的先后顺序以直线方式 单条顺序执行
控制机制

  • CS:主存中代码段的段基地址
  • EIP:将要执行指令的偏移地址
  • 处理器自动增量EIP

设计要点

  • 如何选择简单有效的算法
  • 如何选择存储单元和工作单元

由于顺序程序结构就是一条线的往下执行,所以很简单,举几个例子也就明白了。
例1.1 自然数求和程序

  • 1+2+3+…+N=?
  • 等差数列求和:(1+N)*N/2
.data num dword 3456 sum qword ?
.code mov eax,num add eax,1 mul num shr edx,1       //无符号数,进行逻辑移位rcr eax,1       //带进位的循环移位,保证edx的最低位移位到eax的最高位mov dword ptr sum,eax mov dword ptr sum + 4,edx

例1.2 显示CPU的Vendor信息
CPUID指令:EAX=0,获取CPU的供应商信息,返回结果存储在EBX,EDX,ECX寄存器

include io32.inc .data
buffer byte 'The processor vendor ID is ',12 dup(0),0
buffersize = sizeof buffer .code
start: mov eax,0 cpuid mov dword ptr buffer+buffersize - 13,ebx mov dword ptr buffer+buffersize - 9,edx mov dword ptr buffer+buffersize - 5,ecx mov eax,offset buffer call dispmsg exit 0 end start

例1.3 复杂的表达式计算
编写程序完成表达式R=((XY+5)+4X)/Z的计算
X,Y,Z 均为DWORD类型的变量

Mov eax,X
Imul Y
add eax,5
Adc edx,0
Mov ebx,eax
Mov ecx,edx
Mov eax,X
mov esi,4
imul esi
add eax,ebx
Adc edx,ecx
Idiv Z
Mov R,eax
Mov R+4,edx

2.分支程序结构

目标:

  1. 理解分支结构的机器实现
  2. 掌握判断条件的实现与转移指令
  3. 了解分支结构优化方法

要点

  1. 条件的实现
  2. 条件流程控制
  3. 转移寻址和寻址方式

高级语言与汇编语言的if结构对比

高级语言

  • 采用if语句,并根据条件表达式的 结果转向不同的程序分支

汇编语言

无明确的高级逻辑结构硬指令,通 过比较和跳转指令组合实现

  1. 用比较cmp、and或sub操作影 响(修改)状态标志
  2. 用条件转移指令判断标志位, 并产生到新地址的分支(跳转到 新地址)
if (op1==0)                    Cmp op1,0
{                               Je L1x=1; y=2;                        mov x,0}                                mov y,0else                         jmp L2
{                           L1:x=0;y=0 ;                      mov x,1
}                               mov y,2L2:

常用的影响状态标志的指令
逻辑指令

  • AND,OR,NOT,XOT,TEST

位运算

  • SHL,SHR,SAL,SAR,ROL,ROR,RCL,RCR

算数运算指令

  • ADD,ADC,SUB,SBB,CMP

CPU状态标志

CMP指令

格式:

  • CMP dest, src

影响标志:

  • 溢出OF,符号SF,零ZF,进位CF,辅助进位AF,奇偶PF

转移指令

流程控制机制:

  • 代码段寄存器CS指示代码段基地址
  • 指令指针寄存器EIP指示将要执行指令的偏移地址
  • 顺序执行,根据指令字节长度增加EIP
  • 分支执行,根据目的地址修改EIP或CS

分类

  • 转移范围:段内、段间
  • 寻址方式:相对、直接、间接

    1. 转移范围
    段内转移:当前代码段范围内的转移
  • 只改变EIP(偏移地址)
  • 近转移(Near)NEAR32,NEAR16
  • 短转移(Short)转移范围在127~-128字节

段间转移:不同代码段之间的转移

  • 更改CS(段地址)和EIP(偏移地址)
  • 远转移(Far) FAR32 ,FAR16
  • 32位线性地址空间,48位远转移FAR32
  • 实地址存储模型,32位远转移FAR16

2. 指令寻址方式
确定下一条指令的方法,操作数的形式
相对寻址方式(段内转移)

  • 指令代码提供目标地址相对于当前EIP的位移量
  • 操作数(位移量)=目标地址 - 当前EIP
  • 目标地址(新EIP值)= EIP + 位移量

直接寻址方式(段间转移)

  • 指令代码直接提供目标地址
  • 操作数 = 目标地址
  • 新的CS:EIP = 操作数高地址字:操作数低地址双字

间接寻址方式

  • 指令代码指示寄存器或存储单元,目标地址来自寄存器或存储单元
  • 操作数 = reg / mem
  • 目标地址 = [reg] /[mem]

2.1 无条件转移指令JMP

程序无条件改变执行顺序,相当于C/C++的goto
JMP指令的段内寻址方式:

  1. 段内转移、相对寻址
    标号指明目标地址,指令代码包含位移量
    JMP label ;JMP newaddr
    EIP ← EIP+位移量 –
  2. 段内转移、间接寻址
    通用寄存器或主存单元包含目标指令偏移地址
    JMP reg32/reg16 ;JMP ebx
    EIP ←reg32/reg16
    JMP mem32/mem16 ;JMP near ptr [ebx]
    EIP ←[mem32]/[mem16]
  3. 段间转移、直接寻址
    标号提供所在段的段选择器和偏移地址
    JMP label
    EIP = label的偏移地址
    CS=label的段选择器
  4. 段间转移、间接寻址
    32位线性地址空间用3字存储单元包含目标地址
    JMP m48 ;JMP far ptr [ebx]
    EIP = mem48
    CS = mem48+4
    16位实地址用双字存储单元包含目标地址
    JMP mem32 ;JMP far ptr [ebx]
    EIP = mem32
    CS = mem32+2

MASM会根据存储模式等信息自动识别
平展存储模式常用格式

1.相对寻址
– JMP label

  • JMP near ptr label
  • JMP label

2.寄存器间接寻址
– JMP reg32

  • JMP ebx

3.存储器间接寻址
– JMP mem32

  • JMP near ptr [ebx]

JMP相对寻址方式
格式:JMP label                         操作:EIP =EIP+位移量
位移量=label(目标地址)相对于当前EIP的字节数
范围:

  • 近转移(Near) 范围32位有符号数
  • 短转移(Short)范围 8位有符号数
include io32.inc.data.code
start:mov   eax,5cmp    eax,0jz L1add   ebx,10jmp   near ptr L2
L1:sub  ebx,10
L2:exit 0end    start

无条件转移程序

.datanvar    dword   ?
.code
start:jmp       labl1   //相对寻址nop
labl1:jmp       near ptr labl2nop
labl2:mov       eax,offset labl3jmp     eax     //寄存器间接寻址nop
labl3:mov       eax,offset labl4mov     nvar,eaxjmp     nvar    //存储器简介寻址nop
labl4:exit 0end start

2.2 条件转移指令

不影响标志,利用标志
当状态标志条件为真时,转移到目标地址;否则,顺序 执行下一条指令
格式: Jcc label
label:目标地址,段内相对寻址

  • 32位IA32处理器, 32位的全偏移量

cc:一个或多个标志位的标志位条件

  • JC, JNC,JZ,JNZ,…
include  io32.inc
.code
start:mov       ebx,5cmp        eax,0jz     L1add       ebx,10jmp       L2
L1:sub      ebx,10
L2:exit 0end        start

条件转移指令分类
1.单状态标志类
基于特定标志位的值(单标志位)

  • JZ,JC,JP,JO,JS
  • JNZ,JNC,JNP,JNO,JNS

基于相等性( ZF位)

  • JE,JNE

2.组合状态标志类
无符号数的比较(ZF判断相对,CF位判断大小)

  • JA,JB,JNA,JNB,JAE,JBE…

有符号数的比较(ZF判断相对,SF和OF位判断大小)

  • JG,JL,JNG,JNL,…

    例 个数折半程序
    将某数组分成元素个数相当的两部分.
 Mov     eax,lengthof m1shr      eax,1jnc        is_even                 jc  is_oddjmp   is_evenadd      eax,1           Is_odd:add  eax,1
Is_even:call    dispuid

优化
分支程序是影响程序性能的重要因素之一

Mov      eax,lengthof    m1
shr     eax,1
adc     eax,0
call    dispuid

当数组长度达到最大(eax=0ffffffffh)会怎样?
例 位测试程序
输入参数eax=1的cpuid指令可以获取CPU特性参数
返回参数edx的bit18代表是否支持PSN(Processor Serial Number)功能,1支持,0不支持

include  io32.inc
.datayes_msg    byte    'PSN supported:Yes',0no_msg   byte    'PSN supported:No',0
.code
start:mov       eax,1cpuidtest  edx,040000hmov      edx,offset no_msgjz     dispmov     eax,offset yse_msg
disp:call   dispmsgexit 0end        start

2.3 单分支结构

类似于高级语言的if – then结构语句

  • 当条件满足,发生转移,跳过分支体
  • 条件不满足,顺序向下执行分支体

要点:与if语句相反

  • 转移指令,条件不成立执行分支体
  • if语句,条件成立执行分支体

    例 求绝对值

    例 小写字母转大写字母 ‘a’ = 61h ‘A’ = 41h

2.4 双分支结构

相当于高级语言的if – then - else语句
使用转移指令J(cc)和Jmp实现分支控制
优化为单分支结构

  • 预先执行使用频率较高、不影响判断标志的分支
    例 显示ebx中的最高位

2.5 多分支程序

分支处理中又有嵌套的分支,具有多个分支走向

  • 利用单分支和双分支结构实现多个分支结构


变量地址表程序

复合表达式的实现

C++语言:                  汇编语言:                优化:
if (a > b) && (b>c)           Mov eax,b               Mov eax,b
{                               Cmp a,eax               Cmp a,eaxx=1;                          Ja L1                   Jbe next
}                               jmp next                Cmp eax,cL1:                        Jbe nextCmp eax,c               Mov x,1Ja L2                Next:jmp next L2: Mov x,1 Next:

3.循环程序结构

组成部分

  • 循环初始:为开始循环准备必要的条件,如循环次 数、必要的初始值;
  • 循环体:重复执行的程序代码,包括对循环条件的 修改;
  • 循环控制:判断循环条件是否成立,决定是否继续 循环

“先判断、后循环”的循环程序结构

  • 对应C/C++语言的while语句

“先循环、后判断”的循环程序结构

  • 对应C/C++语言的do语句

3.1 循环指令

例 数组求和程序

//循环初始mov        ecx,lengthof array              //ECX = 数组元素个数xor      eax,eax                         //求和初值为0mov     ebx,eax                         //数组指针为0//循环体
again:add       eax,array[ebx*(type array)] //求和inc     ebx                         //指向下一个数组元素//循环控制loop   againmov        sum,eax                     //保存结果call  dispsid                     //显示结果

3.2 计数控制循环

通过次数控制循环

  • 利用LOOP指令属于计数控制
  • 常见是“先循环、后判断”循环结构

计数可以减量进行,即减到0结束
计数可以增量进行,即达到规定值结束

例 求最大值程序

3.3 条件控制循环

根据条件决定是否进行循环

  • 需要使用有条件转移指令实现
  • 多见“先判断、后循环”结构

先行判断的条件控制循环程序

  • 很像双分支结构
  • 主要分支需要重复执行多次 (JMP的目标位置是循环开始)
  • 另一个分支用于跳出这个循环

先行循环的条件控制循环程序

  • 类似单分支结构,循环体就是分支体
  • 顺序执行就跳出循环

例 字符数字统计程序

 .data
string  byte 'Do you have fun with Assembly?',0       //以0结尾的字符串.code
start:  xor     ebx,ebx     //EBx用来记录字符个数,同事也用于指向字符的指针
again:mov       al,string[ebx]cmp       al,0        //用指令“test al,al”更好jz       doneinc     ebx         //个数加1jmp       again       //继续循环
done:mov        eax,ebx     //显示个数call  dispuidexit 0end        start

3.4 多重循环

实际的应用问题

  • 单纯的分支或循环结构
  • 循环体中具有分支结构
  • 分支体中采用循环结构
  • 循环体中嵌套有循环,即形成多重循环结构

如果内外循环之间没有关系

  • 比较容易处理

如果需要传递参数或利用相同的数据

  • 问题比较复杂

例 冒泡法排序程序

 mov ecx,count       ;ECX←数组元素个数 dec ecx             ;元素个数减1为外循环次数
outlp:  mov edx,ecx         ;EDX←内循环次数 mov ebx,offset array
inlp: mov eax,[ebx]          ;取前一个元素 cmp eax,[ebx+1]    ;与后一个元素比较 jng next   ;前一个不大于后一个,不交换 xchg eax,[ebx+1]     ;否则,进行交换 mov [ebx],eax
next: inc ebx                ;下一对元素 dec edx jnz inlp             ;内循环尾 loop outlp             ;外循环尾

汇编语言(四) - 程序结构相关推荐

  1. c语言饿结构_C语言的四种程序结构

    C语言的四种程序结构 尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电 ...

  2. 程序结构程序设计(四)

    程序结构&&程序设计 程序结构&&程序设计(二) 程序结构&&程序设计(三) --递归 程序结构&&程序设计(三) 程序结构&& ...

  3. 【汇编语言】多模块程序结构

    多模块程序结构 文章目录 多模块程序结构 一.多模块方法 (1)源文件包含 (2)模块连接 (3)子程序库和库文件包含 1.子程序库 2.库文件包含 二.宏汇编 (1)宏汇编的定义 (2)宏定义.宏调 ...

  4. itpt_TCPL 第四章:函数和程序结构

    2016.08.30 – 10.09 个人英文阅读练习笔记(极低水准). 08.30 第四章:函数和程序结构 函数能够将大型的计算任务分解为多个小型的计算任务,并且程序员还能够利用别人已经编写好的函数 ...

  5. 第四节 基本命令和程序结构控制(1)

    第四节 基本命令和程序结构控制(1) 2010年06月22日 第四节 基本命令和程序结构控制(1) 前面几节我们讲解了ActionScript的基础知识,相信你已经对ActionScript的编程方法 ...

  6. 雨落C++小课堂第四课——C++程序结构(4)

    hello,大家好,在下雨落,最近雨落正在疯狂补习C++啊,终于明白了为什么程序员一般会"秃头"啊,不说了,上标题-- C++程序结构(4) 接着上次地讲-- 嗯,这是为什么呢,我 ...

  7. python编程语法-Python学习笔记(Ⅰ)——Python程序结构与基础语法

    作为微软的粉丝,最后终于向Python低头了,拖了两三个月终于下定决心学习Python了.不过由于之前受到C/C#等语言影响的思维定式,前期有些东西理解起来还是很费了些功夫的. 零.先抄书: 1.Py ...

  8. Python学习笔记(Ⅰ)——Python程序结构与基础语法

    作为微软的粉丝,最后终于向Python低头了,拖了两三个月终于下定决心学习Python了.不过由于之前受到C/C#等语言影响的思维定式,前期有些东西理解起来还是很费了些功夫的. 零.先抄书: 1.Py ...

  9. python的类程序的结构_python(8)---程序结构

    在计算机编程中,面向过程的编程中,程序结构分为三类:顺序结构.分支结构.循环结构. 一.顺序结构 顺序结构就是指程序一步一步按照顺序执行程序,顺序结构比较简单. 二.分支结构 分支结构主要就是逻辑判断 ...

最新文章

  1. qtablewidget 数据量大效率很低_让大牛带你走进大数据分析:R基础及应用的潮流尖端,享受RHadoop...
  2. Jquery-基础知识点
  3. 链表的数据域怎么使用结构体_一步一步教你从零开始写C语言链表
  4. java 读取 image_如何在java读取sql里头读取image格式的数据转换成图片格式
  5. mysql ==null_mysql = null 问题
  6. Proxy Hosted Virtual
  7. 智慧城市数据采集的四大难点分析及解决措施
  8. NYOJ813 - 对决
  9. SWIFT IOS开发 部分compile error
  10. 扇贝有道180917每日一句
  11. 皕杰报表使用技巧:竖排文字如何输入
  12. 软件工程之项目开发计划
  13. 数据库的备份与恢复技术
  14. Discuz门户模板乱码解决方案
  15. Django基础(29): select_related和prefetch_related的用法与区别
  16. 最优化理论与方法1--理论基础
  17. matlab等距偏置曲线,144 偏置曲线命令详解
  18. Echarts中国地图各省份区域设置不同的颜色
  19. 5、Dubbo-监控中心
  20. 用sealed修饰的类有什么特点

热门文章

  1. python 学习指南_Python学习指南
  2. OSChina 周四乱弹 —— 去跳跳广场舞不好么
  3. C# Excel.Range类实现对Excel单元格文本格式的设置
  4. jsp中java如何使用js_如何在jsp中使用javascript
  5. 一个自律、努力且有计划的人,注定成为人生赢家!!!
  6. 炒股成功的人可怕到令普通人难以想象!
  7. 【演歌】函館の女 歌词翻译
  8. 李宏毅深度强化学习笔记
  9. fs(文件系统——文件操作)
  10. Unity UIToolkit