在《第一个汇编语言程序》一节中给出的 AddTwo 程序,并添加必要的声明使其成为完全能运行的程序。

  ; AddTwo.asm -两个 32 位整数相加    .386  .model flat,stdcall  .stack 4096  ExitProcess PROTO, dwExitCode:DWORD    .code  main PROC  mov  eax,5  ;将数字5送入eax寄存器  add      eax,6  ;eax寄存器加6    INVOKE ExitProcess,0  main ENDP  END main

第 3 行是 .386 伪指令,它表示这是一个 32 位程序,能访问 32 位寄存器和地址。第 4 行选择了程序的内存模式(flat),并确定了子程序的调用规范(称为 stdcall)。其原因是 32 位 Windows 服务要求使用 stdcall 规范。第 5 行为运行时堆栈保留了 4096 字节的存储空间,每个程序都必须有。

第 6 行声明了 ExitProcess 函数的原型,它是一个标准的 Windows 服务。原型包含了函数名、PROTO 关键字、一个逗号,以及一个输入参数列表。ExitProcess 的输入参数名称为 dwExitCode。

可以将其看作为给 Windows 操作系统的返回值,返回值为零,则表示程序执行成功;而任何其他的整数值都表示了一个错误代码。因此,程序员可以将自己的汇编程序看作是被操作系统调用的子程序或过程。当程序准备结束时,它就调用 ExitProcess,并向操作系统返回一个整数以表示该程序运行良好。

大家可能会好奇,为什么操作系统想要知道程序是否成功完成。理由如下:与按序执行一些程序相比,系统管理员常常会创建脚本文件。在脚本文件中的每一个点上,系统管理员都需要知道刚执行的程序是否失败,这样就可以在必要时退出该脚本。

脚本通常如下例所示,其中,ErrorLevel1 表示前一步的过程返回码大于或等于 1 :

  call program_1  if ErrorLevel 1 goto FailedLabel  call program_2  if ErrorLevel 1 goto FailedLabel  :SuccessLabel.  Echo Great, everything worked!

现在回到 AddTwo 程序清单。第 15 行用 end 伪指令来标记汇编的最后一行,同时它也标识了程序的入口(main)。标号 main 在第 9 行进行了声明,它标记了程序开始执行的地址。

汇编伪指令回顾

现在回顾一些在示例程序中使用过的最重要的汇编伪指令。

首先是 .MODEL 伪指令,它告诉汇编程序用的是哪一种存储模式:

  .model flat,stdcall

32 位程序总是使用平面(flat)存储模式,它与处理器的保护模式相关联。关键字 stdcall 在调用程序时告诉汇编器,怎样管理运行时堆栈。然后是 .STACK 伪指令,它告诉汇编器应该为程序运行时堆栈保留多少内存字节:

  .stack 4096

数值 4096 可能比将要用的字节数多,但是对处理器的内存管理而言,它正好对应了一个内存页的大小。所有的现代程序在调用子程序时都会用到堆栈。首先,用来保存传递的参数;其次,用来保存调用函数的代码的地址。

函数调用结束后,CPU 利用这个地址返回到函数被调用的程序点。此外,运行时堆栈还可以保存局部变量,也就是,在函数内定义的变量。

.CODE 伪指令标记一个程序代码区的起点,代码区包含了可执行指令。通常,.CODE 的下一行声明程序的入口,按照惯例,一般会是一个名为 main 的过程。程序的入口是指程序要执行的第一条指令的位置。用下面两行来传递这个信息:

  .code  main PROC

ENDP 伪指令标记一个过程的结束。如果程序有名为 main 的过程,则 endp 就必须使用同样的名称:

  main ENDP

最后,END 伪指令标记一个程序的结束,并要引用程序入口:

  END main

如果在 END 伪指令后面还有更多代码行,它们都会被汇编程序忽略。程序员可以在这里放各种内容一一程序注释,代码副本等等,都无关紧要。

运行和调试 AddTwo 程序

使用 Visual Studio 可以很方便地编辑、构建和运行汇编语言程序。下面的步骤,按照 Visual Studio 2012,说明了怎样打开示例项目,并创建 AddTwo 程序:

1) 启动计算机上安装的最新版本的 Visual Studio。

2) 打开 Visual Studio 中 Solution Explorer 窗口。它应该已经是可见的,但是程序员也可以在 View 菜单中选择 Solution Explorer 使其可见。

3) 在 Solution Explorer 窗口右键点击项目名称,在文本菜单中选择 Add,再在弹出菜单中选择 New Item。

4) 在 Add New File 对话窗口中(如下图所示 ) ,将文件命名为 AddTwo.asm,填写 Location 项为该文件选择一个合适的磁盘文件夹。

5) 单击 Add 按钮保存文件。

6) 键入程序源代码,如下所示。这里大写关键字不是必需的:

  ; AddTwo.asm - adds two 32-bit integers.    .386  .model flat,stdcall  .stack 4096  ExitProcess PROTO,dwExitCode:DWORD    .code  main PROC  mov eax, 5  add eax, 6    INVOKE ExitProcess,0  main ENDP  END main

7) 在 Project 菜单中选择 Build Project,查看 Visual Studio 工作区底部的错误消息。这被称为错误列表窗口。注意,当没有错误时,窗口底部的状态栏会显示 Build succeeded。

调试演示

下面将展示 AddTwo 程序的一个示例调试会话。演示使用的是 Visual Studio 2012,不过,自 2008 年起的任何版本的 Visual Studio 都可以使用。

运行调试程序的一个方法是在 Debug 菜单中选择 Step Over。按照 Visual Studio 的配置,F10 功能键或 Shift+F8 组合键将执行 Step Over 命令。

开始调试会话的另一种方法是在程序语句上设置断点,方法是在代码窗口左侧灰色垂直条中直接单击。断点处由一个红色大圆点标识出来。然后就可以从 Debug 菜单中选择 Start Debugging 开始运行程序。

如果试图在非执行代码行设置断点,那么在运行程序时,Visual Studio 会直接将断点前移到下一条可执行代码行。

当调试器被激活时,Visual Studio 窗口底部的状态栏变为橙色。当调试器停止并返回编辑模式时,状态栏变为蓝色。可视提示是有用的,因为在调试器运行时,程序员无法对程序进行编辑或保存。

自定义调试接口

在调试时可以自定义调试接口。例如,如果想要显示 CPU 寄存器,实现方法是,在 Debug 菜单中选择 Windows,然后再选择 Registerso, 其中 Registers 窗口可见,同时还关闭了一些不重要的窗口。EAX 数值显示为 0000000B,是十进制数 11 的十六进制表示。

Registers 窗口中,EFL 寄存器包含了所有的状态标志位(零标志、进位标志、溢出标志等)。如果在 Registers 窗口中 右键单击,并在弹出菜单中选择Flags,则窗口将显示单个的标志位值。

Registers 窗口的一个重要特点是,在单步执行程序时,任何寄存器,只要当前指令修改了它的数值,就会变为红色。尽管无法在打印页面(它只有黑白两色)上表示出来,这种红色高亮确实显示给程序员,使之了解其程序是怎样影响寄存器的。

在 Visual Studio 中运行一个汇编语言程序时,它是在控制台窗口中启动的。这个窗口与从 Windows 的 Start 菜单运行名为 cmd.exe 程序的窗口是相同的。或者,还可以打开项目 DebugBin 文件夹中的命令提示符,直接从命令行运行应用程序。如果采用的是这个方法,程序员就只能看见程序的输出,其中包括了写入控制台窗口的文本。查找具有相同名称的可执行文件作为 Visual Studio 项目。

下一篇:汇编器

强力推荐阅读文章

年薪40+W的大数据开发【教程】,都在这儿!

汇编语言整数加减法示例相关推荐

  1. 汇编语言数据传送示例

    ;数据传送示例 .386 .model flat,stdcall .stack 4096 ExitProcess PROTO,dwExitCode:DWORD .data val1 WORD 1000 ...

  2. boost::sort模块实现spreadsort 64 位整数排序示例

    boost::sort模块实现spreadsort 64 位整数排序示例 实现功能 C++实现代码 实现功能 boost::sort模块实现spreadsort 64 位整数排序示例 C++实现代码 ...

  3. python计算时间差代码_Python3显示当前时间、计算时间差及时间加减法示例代码...

    Python3显示当前时间.计算时间差及时间加减法示例代码 摘要 在使用Python写程序时,经常需要输出系统的当前时间以及计算两个时间之间的差值,或者将当前时间加减一定时间(天数.小时.分钟.秒)来 ...

  4. Golang大整数计算示例-阶乘

    Golang大整数计算示例-阶乘 代码 解析 运行结果 其他说明 结论 代码 直接上代码: package mainimport "fmt" import "math/b ...

  5. python罗马数字转换,Python3.5实现的罗马数字转换成整数功能示例

    本文实例讲述了Python3.5实现的罗马数字转换成整数功能.分享给大家供大家参考,具体如下: 问题概述: 给定一个罗马数字 ,将罗马数字转换成整数. 如罗马数字I,II,III,IV,V分别代表数字 ...

  6. 大整数加减法(基础,细节题型)

    大数加法 51Nod - 1005 给出2个大整数A,B,计算A+B的结果. Input 第1行:大数A 第2行:大数B (A,B的长度 <= 10000 需注意:A B有可能为负数) Outp ...

  7. 100999凑整到万位进一_【小学奥数题库系统】1-1-1-1 整数加减法速算与巧算.教师版...

    另一个数的"补数". 2.加补凑整法.有些算式中直接凑整不明显,这时可"借数"或"拆数"凑整. 3.数值原理法.先把加在一起为整十.整百.整 ...

  8. 汇编语言零基础入门学习教程

    汇编语言是一种最低级.最古老.不具有移植性的编程语言,它能够直接访问计算机硬件,所以执行效率极高,占用资源极少,一般用于嵌入式设备.驱动程序.实时应用.核心算法等. 汇编语言的缺点是开发周期特别长,实 ...

  9. # 异运算_小学数学整数、小数、分数加减法运算法则及练习(可打印)

    很多孩子的数学不好,尤其是女孩子.家长往往认定为数学不好就是孩子不擅长,能力差. 其实未必,有的孩子数学不好的原因并不在于智商,而是没有理解到数学的方法与逻辑.比如小学的运算中,很多孩子并没有了解到运 ...

最新文章

  1. 最全总结!聊聊 Python 操作PDF的几种方法
  2. 《CSS揭秘》笔记(一)
  3. Java基础-数据类型int,short,char,long,float,double,boolean,byte
  4. 电子书下载:Pro Drupal 7 for Windows Developers
  5. 【Vue】脚手架 Vue CLI 的使用
  6. 直播 | 智能仓库:端侧 AI 和 OpenVINO 落地实践
  7. AppStore刷榜那些事儿:猪,也是这么想的
  8. 服务器物理槽位和逻辑对应,如何查看Linux服务器的物理CPU逻辑CPU和CPU核数
  9. oracle系统物料事务处理类型,Oracle_EBS_斌力十足系列_INV库存模块操作手册_杂项事务处理的分类和实际业务的应用场景专题研究报告...
  10. 使用windows内存-内存映射文件
  11. 潮流能模型matlab,基于matlab的yalmip最优潮流建模的Infeasible problem
  12. php 三消算法,三消游戏关卡设计教程(初级篇)——基本地形设计
  13. python numpy库数组的存取
  14. 【网站介绍】有意思的网站(备忘)
  15. 回文素数(10亿)—— unfinished
  16. Android camera2 同时打开两颗物理摄像头
  17. 卡尔曼滤波简介(转载)
  18. 计算机应用二级客观题,计算机二级客观题
  19. android 瘦脸模式 sdk,大眼瘦脸加磨皮通通不能少,论美颜SDK是如何实现的
  20. Notion——Android版下载与注册登录

热门文章

  1. 【linux】虚拟机安装centos后ping ip地址出现错误:Network is unreachable
  2. Python学习笔记007_图形用户界面[EasyGui][Tkinter]
  3. HOJ 2576 HOJ 2577 Simple Computing I II 容斥原理
  4. 利用Web Services实现软件自动升级
  5. 一招一式, 成就“霸业”必做的9件大事
  6. Golang 学习笔记资源
  7. 文件内存映射mmap解决大文件快速读写问题和进程间共享内存
  8. php母版页怎么,ASP.NET
  9. 组会20211008《kEMPO1粒子模拟核心代码注释》
  10. [云炬创业基础笔记]第七张创业团队测试9