3.15学习——汇编语言初学习

前言——汇编语言的出现

1.了解CPU

什么是CPU:了解CPU
CPU执行的的指令是机器指令,机器指令是由0和1组成的二进制编码。CPU所能直接理解和执行的直流就是机器语言,而这些指令在底层上来说是以二进制的形式存在,是计算机硬件能够直接识别的最基本形式

101111000    1110000     1111110000

2.从机器语言到汇编指令的转变

汇编语言的提出概括地来说是由于人类需要一种易于理解和阅读的语言。汇编语言也就是在这种背景下诞生的。
汇编语言是一种使用助记符来表示机器指令的语言。每一条汇编指令直接映射到一条机器指令,例如:

  1. MOV 表示将数据移动到寄存器
  2. JMP 表示无条件跳转
  3. ADD 表示将两个两个数相加

汇编语言的出现本质上就是为了方便程序员的编写 ,使用符号化的语言来代替机器语言

3.汇编语言的编译过程

汇编语言不能被计算机执行,需要借助汇编器将汇编语言转化为机器语言
例如:
汇编指令MOV EAX, 1在汇编器的作用下会被转化为 B8 01 00 00 00从而被CPU执行

机器语言
10111000 00000001 00000000 00000000
汇编语言
MOV EAX, 1

4.汇编语言的组成

1.汇编指令:机器码的助记符,有对应的机器码。
2.伪指令:没有对应的机器码,由编译器执行,计算机不会执行。
3.其他符号:+、-、*等,由编译器识别,没有对应的机器码。

CPU架构

CPU架构介绍
不同的架构决定了汇编语言的编写规则和标准

1.x86架构

x86架构是Intel推出的16位处理器架构。经过多次扩展,发展成为了如今的32位(x86)和64位(x86-64)架构
x86-64架构是AMD推出后被Intel采用,这种架构与32位的x86架构指令兼容,同时也引用了更多寄存器和指令扩展,也是现在电脑端运用最广泛的架构。很多CTF的PC端逆向都是这种架构在这里插入图片描述最早的x86-64指令集是Intel在8086处理器中首创出,后被全球广泛使用

2.ARM架构

与x86架构不同,ARM架构在移动端运用更广,很多手机和平板甚至部分Windows10和11会采用这种架构在这里插入图片描述

不同架构汇编指令的区分

1.x86汇编

适用于32位程序和32位处理器
x86指令集:最早基于Intel 8086处理器架构,原本是16位架构,后来发展为32位架构。x86汇编语言用于32位处理器,其指令和寄存器都与32位处理器兼容。

2.x64汇编(也叫AMD64汇编)

适用于64位程序及64位处理器
x64指令集是对x86指令集的64位扩展,最早由AMD提出并实现。与x86相比多了很多扩展,例如:
使用64位寄存器(RAX,RBX,RCX),代替了32位寄存器(EAX,EBX,ECX)
支持更多的汇编指令等

关于x64汇编指令集在[Intel-64 和 IA-32 体系结构软件开发手册]有详细描述(https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html)

认识常见的汇编指令

先举个例子,这是一个简单的C源文件,当执行程序的时候会输出个hello
world
在这里插入图片描述可以用gcc编译器将c源文件转换为汇编语言在这里插入图片描述

	.file	"\346\261\207\347\274\226.c"
	.text
	.section .rdata,"dr"
.LC0:
	.ascii "world\0"
.LC1:
	.ascii "hello %s\12\0"
	.text
	.globl	main
	.def	main;	.scl	2;	.type	32;	.endef
	.seh_proc	main
main:
	pushq	%rbp
	.seh_pushreg	%rbp
	movq	%rsp, %rbp
	.seh_setframe	%rbp, 0
	subq	$32, %rsp
	.seh_stackalloc	32
	.seh_endprologue
	movl	%ecx, 16(%rbp)
	movq	%rdx, 24(%rbp)
	call	__main
	leaq	.LC0(%rip), %rax
	movq	%rax, %rdx
	leaq	.LC1(%rip), %rax
	movq	%rax, %rcx
	call	printf
	movl	$0, %eax
	addq	$32, %rsp
	popq	%rbp
	ret
	.seh_endproc
	.def	__main;	.scl	2;	.type	32;	.endef
	.ident	"GCC: (Rev2, Built by MSYS2 project) 14.2.0"
	.def	printf;	.scl	2;	.type	32;	.endef

这是转换出来的汇编代码,注意汇编程序由三个不同的元素组成:

指示(Directives) 以点号开始,用来指示对编译器,连接器,调试器有用的结构信息。指示本身不是汇编指令。例如,.file 只是记录原始源文件名。.data表示数据段(section)的开始地址, 而 .text 表示实际程序代码的起始。.string 表示数据段中的字符串常量。 .globl main指明标签main是一个可以在其它模块的代码中被访问的全局符号 。至于其它的指示你可以忽略。

标签(Labels) 以冒号结尾,用来把标签名和标签出现的位置关联起来。例如,标签.LC0:表示紧接着的字符串的名称是 .LC0. 标签main:表示指令 pushq %rbp是main函数的第一个指令。按照惯例, 以点号开始的标签都是编译器生成的临时局部标签,其它标签则是用户可见的函数和全局变量名称。

指令(Instructions) 实际的汇编代码 (pushq %rbp), 一般都会缩进,以便和指示及标签区分开来。
注:
不同的C语言编辑器编辑出的c源文件用gcc汇编后是不一样的,就像上面是用Vistaul studio编辑的,用gcc编译的汇编代码看上去和目前阶段CTF中的伪C代码很不一样

其中很常用的几个:

1.MOV 指令

可以用英语单词move来理解,所起到的作用与移动,传送有关
MOV指令可以实现将数据在内存,寄存器之间互相传送
mov指令的顺序是从右到左,如mov a,b,则把b的值复制给a,即a=b
如:

mov     rax, 'hgfedcba'

就是将’hgfedcba’传到rax寄存器里面

2.lea指令

lea,官方解释Load Effective Address,即加载有效地址到目标寄存器中的意思,看上去跟mov指令的作用很像,但二者存在区别。
比如:

lea     rax, aFlagS

这里的意思是将flag的地址加在到rax寄存器中
二者的区别在于:
·mov 指令用于在寄存器或内存之间传输数据值。
·lea 指令用于计算有效地址,并将结果加载到寄存器中,但不访问该地址处的内存内容。
我的理解是mov指令是跟数据值打交道,而lea指令是跟地址有关

3.call指令

call指令用英语来理解就是呼叫调用,也就是起到调用函数的作用,如:

call    printf

就是调用printf(打印)函数

4.push指令与pop指令

push 指令用于将一个寄存器或值压入栈中的指令,相对的pop指令就是出栈指令,用于将值从栈中弹出到一个寄存器或内存位置。
如:

 push    rbp

这段指令的意思是将基址指针寄存器rbp压入栈中以保存其值

pop      rbp

将当前栈顶的 8 字节数据弹出到 rbp 寄存器,并将堆栈指针 rsp 增加 8 字节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值