当前位置:   article > 正文

汇编语言是什么?

汇编语言

基础定义

助记符
例如在加法运算的本地代码中加上 add(addition的缩写)、在比较运算的本地代码中加上 cmp(compare 的缩写)等
这些缩写称为助记符

汇编语言:使用助记符的编程语言称为汇编语言

汇编器:把汇编源代码转换成本地代码的程序叫作汇编器

汇编:汇编器转换的过程称之为汇编

汇编语言的语法

语法结构:是操作码 + 操作数 A(也存在只有操作码没有操作数的指令)
备注:在高级编程语言的源代码中,即使指令和数据在编写时是分散的,编译后也会在段定义中集合汇总起来
图:
在这里插入图片描述

汇编语言与 C 语言的区别
1、汇编语言的源代码和本地代码是一一对应的
图:
在这里插入图片描述

2、C 语言的源代码同本地代码不是一一对应的 ?
备注:会添加相应的段定义,伪代码和引用的文件库
图:接着往下看

常用指令

mov指令
指令中最常使用的是对寄存器和内存进行数据存储,mov 指令的两个操作数,分别用来指定数据的存储地和读出源

mov ebp,esp 
mov eax,dword ptr [ebp+8]
  • 1
  • 2

push、pop指令
栈是存储临时数据的区域,它的特点是通过 push 指令和 pop 指令进行数据的存储和读出
图:
在这里插入图片描述

函数的调用机制

C 语言源码

	int AddNum(int a, int b)	
	{
	 return a + b;
	}

	void MyFunc()
	{
	  int c;
	  c = AddNum(123, 456);
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

汇编语言代码

	_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
	_TEXT segment dword public use32 'CODE'
	_AddNum proc near
	 ; 
	 ; int AddNum(int a, int b)
	 ; 
	 push ebp
	 mov ebp,esp
	 ; 
	 ; {
	 ; return a + b;
	 ; 
	 mov eax,dword ptr [ebp+8]
	 add eax,dword ptr [ebp+12]
	 ; 
	 ; }
	 ; 
	 pop ebp
	 ret 
	_AddNum endp
	_MyFunc proc near
	 ; 
	 ; void MyFunc()
	 ; 
	 push ebp
	 mov ebp,esp
	 ; 
	 ; {
	 ; int c;
	 ; c = AddNum(123, 456);
	 ; 
	 push 456
	 push 123
	 call _AddNum
	 add esp,8
	 ; 
	 ; }
	 ; 
	 pop ebp
	 ret 
	_MyFunc endp
	_TEXT ends
	 end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

步骤图:
在这里插入图片描述

备注:栈结构对传入参数进行压入、压出操作,按照编写顺序进行相应值的转换

函数的内部处理机制

特点:“函数的参数是通过栈来传递,返回值是通过寄存器来返回的”

理由:函数调用完毕,使用的栈内存也跟着销毁了,所以将返回值存储到了寄存器当中

为什么局部变量只能在定义该变量的函数内进行参阅呢?
这是因为,局部变量是临时保存在寄存器和栈中的。正如本章前半部分讲的那样,函数内部利用的栈,在函数处理完毕后会恢复到初始状态,因此局部变量的值也就被销毁了,而寄存器也可能会被用于其他目的。因此,局部变量只是在函数处理运行期间临时存储在寄存器和栈上

从汇编语言角度看多线程的安全问题

情景:
在进行函数调用时,发现与预期结果不符

原因分析:
假设 MyFunc1 函数在读出counter 的数值 100 后,还未来得及将它的 2 倍值 200 写入 counter 时,正巧 MyFunc2 函数读出了 counter 的数值 100,那么结果就会导致counter 的数值变成了 200

// 定义全局变量
int counter = 100;
// 定义 MyFunc1 函数
void MyFunc1()
{
 counter *= 2;
}
// 定义 MyFunc2 函数
void MyFunc2()
{
 counter *=2;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
mov eax,dword ptr[_counter] ; 将 counter 的值读入 eax 寄存器
add eax,eax ; 将 eax 寄存器的值扩大至原来的 2 倍
mov dword ptr[_counter],eax ; 将 eax 寄存器的数值存入 counter 中
  • 1
  • 2
  • 3

图:

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/461024
推荐阅读
相关标签
  

闽ICP备14008679号