不会转换成本地代码的伪指令及汇编语言的语法

简介: 不会转换成本地代码的伪指令及汇编语言的语法

一、不会转换成本地代码的伪指令


       汇编代码看起来比较难,不过实际上其实比较简单,而且可能比C语言还要简单,为了便于阅读汇编代码的源代码,需要注意几个要点


       汇编语言的源代码,是由转换成本地代码的指令(后面讲述的操作码)和针对汇编器的伪指令构成的。伪指令负责把程序的构造以及汇编的方法指示给汇编器(转换程序)。不过伪指令是无法汇编转换成为本地代码的。下面是上面程序截取的伪指令


_TEXT segment dword public use32 'CODE'
_TEXT ends
_DATA segment dword public use32 'DATA'
_DATA ends
_BSS segment dword public use32 'BSS'
_BSS ends
DGROUP group_BSS, _DATA
_AddNum proc near
_AddNum endp
_MyFunc proc near
_MyFunc endp
_TEXT ends
end


  由伪指令segment 和 ends 围起来的部分,是给构成程序的命令和数据的集合体上加一个名字而得到的,称为 段定义。段定义的英文表达具有 区域的意思,在这个程序中,段定义指的是命令和数据等程序的集合体的意思,一个程序由多个段定义构成


       上面代码的开始位置,定义了3个名称分别为_TEXT、_DATA、_BSS 的段定义,_TEXT 是指定的段定义,_DATA 是被初始化(有初始值)的数据的段定义,_BSS 是尚未初始化的数据的段定义。这种定义的名称是由Borland C++定义的,是由 Borland C++编译器自动分配的,所以程序段定义的顺序就成为了_TEXT、_DATA、_BSS,这样也确保了内存的连续性


_TEXT segment dword public use32 'CODE'
_TEXT ends
_DATA segment dword public use 'DATA'
_DATA ends
_BSS segment dword public use32 'BSS'
_BSS ends


  段定义(segment)是用来区分或者划分范围区域的意思。汇编语言的segment伪指令表示段定义的起始,ends 伪指令表示段定义的结束。段定义是一段连续的内存空间


而 group 这个伪指令表示的是将_BSS和_DATA 这两个段定义汇总名为 DGROUP 的组


DGROUP group_BSS, _DATA


  围起_AddNum和 _MyFun 的 _TEXT segment 和_TEXT ends,表示_AddNum和_MyFun属于_TEXT 这一段定义的


_TEXT segment dword public use32 'CODE'
_TEXT ends


       因此,即使在源代码中指令和数据是混杂编写的,经过编译和汇编后,也会转换成为规整的本地代码


   _AddNum proc 和 _AddNum endp 围起来的部分,以及 _MyFuncproc 和 _MyFunc endp 围起来的部分,分别表示AddNum函数和MyFunc函数的范围


_AddNum proc near
_AddNum endp
_MyFunc proc near
_MyFunc endp


编译后在函数名前附带上下划线 _ ,是Borland C++ 的规定。在C语言中编写的AddNum函数,在内部是以 _AddNum 这个名称处理的。伪指令 proc 和 endp 围起来的部分,表示的是过程(procedure)的范围。在汇编语言中,这种相当于C语言的函数形式称为过程。末尾的end伪指令,表示的是源代码的结束


二、汇编语言的语法


       在汇编语言中,一行表示一对CPU的一个指令。汇编语言指令的语法结构是操作码+操作数,也存在只有操作码没有操作数的指令。


       操作码表示的是指令动作,操作数表示的是指令对象。操作码和操作数一起使用就是一个英文指令。比如从英语语法来分析的话,操作码是动词,操作数是宾语。比如这个句子 Give me money 这个英文指令的话,Give 就是操作码,me和money就是操作数。汇编语言中存在多个操作数的情况,要用逗号把它们分割,就像是 Give me,money 这样


能够使用何种形式的操作码,是由CPU的种类决定的,下面对操作码的功能进行了整理。


部分操作码及其功能:


操作码 操作数 功能数
mov A,B 把B的值赋给A
and A,B 把A和B同时相加,并把结果赋给A
push A 把A的值存储在栈中
pop A 从栈中读出值,并将其赋值给A
call A 调用函数A
ret 处理返回给调用源函数


本地代码需要加载到内存后才能运行,内存中存储着构成本地代码的指令和数据。程序运行时,CPU会从内存中把数据和指令读出来,然后放在CPU内部的寄存器进行处理

CPU和内存的关系:



寄存器是CPU中的存储区域,寄存器除了有临时存储和计算的功能之外,还具有运算功能,x86系列的主要种类和角色如下图所示


x86系列CPU的主要寄存器:


寄存器名 名称 主要功能
eax 累加寄存器 运算
ebc 基址寄存器 存储内存地址
ecx 计数寄存器 计算循环次数
edx 数据寄存器 存储数据
esi 源基址寄存器 存储数据发送源的内存地址
edi 目的基址寄存器 存储数据发送目标的内存地址
ebp 扩展基址指针寄存器 存储数据存储领域基点的内存地址
esp 扩展栈指针寄存器 存储栈中最高位数据的内存地址
目录
相关文章
|
11月前
|
编译器 Linux C语言
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)(上)
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)
|
2月前
|
网络协议 C++
解决MASM32代码汇编出错: error A2181: initializer must be a string or single item
解决MASM32代码汇编出错: error A2181: initializer must be a string or single item
|
3月前
|
存储 算法 程序员
神秘代码世界惊现高效秘籍!究竟是什么让汇编语言编程如此强大?快来一探究竟!
【8月更文挑战第31天】《代码之美:探索高效汇编语言编程的最佳实践》介绍了汇编语言在系统内核、嵌入式系统及高性能应用中的不可替代作用。书中强调了深入理解处理器架构、提升代码可读性、优化算法与数据结构及有效利用寄存器等最佳实践的重要性。通过具体示例,如在 x86 架构下实现高效的加法函数,展示了如何运用这些技巧编写出既高效又可靠的汇编代码,充分展现了汇编语言的独特魅力及其在现代软件开发中的价值。
40 0
|
2月前
|
Windows
【原创】DOS下TSR程序的汇编演示代码2--黑屏保护程序
【原创】DOS下TSR程序的汇编演示代码2--黑屏保护程序
【原创】DOS下TSR程序的汇编演示代码1--自动按键程序
【原创】DOS下TSR程序的汇编演示代码1--自动按键程序
|
3月前
|
NoSQL 前端开发 程序员
【震撼揭秘!】程序员绝不会告诉你的秘密:掌握汇编语言调试,轻松从软件故障中全身而退——透视代码底层,成为Bug猎人!
【8月更文挑战第31天】《调试的艺术:如何利用汇编语言追踪和解决软件问题》探讨了使用汇编语言进行高效调试的方法。无论是初学者还是资深开发者,面对棘手的 bug 时,高级语言的信息往往不足。文章通过具体示例展示如何通过汇编代码定位问题,如 C 语言中数组求和函数的崩溃问题。借助 `gcc -S` 生成的汇编代码和 GDB 调试器,可以深入理解程序行为,从而更准确地解决问题。掌握这一技能,将使你在复杂问题面前更加从容。
41 2
|
3月前
|
C语言
51单片机汇编语言流水灯代码
51单片机汇编语言流水灯代码
|
3月前
|
C# 开发者 图形学
Xamarin 竟在游戏开发领域大胆探索,跨平台优势与强大功能结合,开启游戏开发新潮流!
【8月更文挑战第31天】《Xamarin在游戏开发领域的探索》介绍了Xamarin作为跨平台开发框架,在移动游戏开发中的应用。它利用C#语言的优势,提供高效的开发体验,并结合各平台图形库实现高质量画面。本文还展示了Xamarin如何简化游戏逻辑处理、支持多线程编程及与Unity等工具集成,提升游戏质量和开发效率。此外,Xamarin还支持热更新和多平台发布,进一步优化游戏维护流程。
40 0
|
6月前
|
Java C++
如何在JAVA代码中嵌入汇编
如何在JAVA代码中嵌入汇编
94 1