汇编入门log(一)
学东西,不做笔记,相当于没学。
听到的,不是你学会的;讲出来的,才是你学会的。
CPU获取数据
CPU只是一个单纯的运算设备,并不存储数据,按照速率快慢,依次从:寄存器、一级缓存、二级缓存,取数据。
而寄存器、一级缓存与二级缓存,都从内存中获取数据。
hello world
不知道从何说起,就从解释hello world开始吧。
一下是汇编hello world代码。
1 | section.text |
汇编程序
汇编程序多种多样,例如
微软汇编程序——MASM
Borland Turbo Assembler——TASM
GNU 汇编程序——GAS
而本文是使用NASM汇编器
汇编的三个部分
汇编程序的三个部分
data部分用于声明初始化数据或常量,该数据在运行时不会改变。
1 | section.data |
bss部分用于声明变量。
1 | section.bss |
text部分用于保存实际代码,该部分以global _start开头,告诉内核程序执行的开始位置。
1 | section.text |
PS.注释
以(;)开头
1 | ; this is an annotation |
汇编的内存段
数据段 - .data与.bss
代码段 - .text
堆栈 - 该段包含传递给程序内的函数和过程的数据值
寄存器
处理器操作主要涉及处理数据,为了加速处理器操作,处理器包含一些内部存储器存储位置,称为寄存器。
- 处理器寄存器
- 通用寄存器
- 数据寄存器
- 指针寄存器
- 索引寄存器
- 控制寄存器
- 段寄存器
- 通用寄存器
通用寄存器
数据寄存器
四个32位的数据寄存器,用于算术、逻辑和其他运算。这些32位寄存器可以通过三种方式使用
- 作为完整的32位数据寄存器:EAX、EBX、ECX、EDX
- 32位寄存器的下半部分可用作四个16位数据寄存器:AX、BX、CX、DX
- 上述4个16位寄存器的下半部分和上半部分可以用作8个8位数据寄存器:AH、AL、BH、BL、CH、CL、DH、DL
(盗图,这个图真的很好,我在文章尾部添加了参考信息)
且
AX为主累加器,用于输入/输出和大多数算数指令
BX为基址寄存器,用于索引寻址
CX为计数寄存器,与ECX一样,存储迭代操作中的循环计数
DX为数据寄存器,用于输入/输出操作。与AX寄存器和DX一起使用,用于设计大值的乘法和除法运算
其他寄存器
其他寄存器,暂时还未熟悉,后续看到相关内容再添加
汇编-系统调用
系统调用是用户空间和内核空间之间接口的API。
可以在汇编程序中使用Linux系统调用,在程序中需要执行以下步骤
- 将系统调用号放入EAX寄存器中
- 将系统调用的参数存储在寄存器EBX、ECX等中
- 调用相关中断(80h)
- 结果通常返回到EAX寄存器中
六个寄存器存储所使用的系统调用的参数,EBX、ECX、EDX、ESI、EDI、EBP
例如,系统调用sys_exit的使用系统调用sys_write的使用1
2mov eax,1 ; system call number (sys_exit)
int 0x80 ; call kernel所有系统调用及其编号(在调用 int 80h 之前放入 EAX 中的值)都列在 /usr/include/asm/unistd.h 中1
2
3
4
5mov edx,4 ; message length
mov ecx,msg ; message to write
mov ebx,1 ; file descriptor (stdout)
mov eax,4 ; system call number (sys_write)
int 0x80 ; call kernel
部分系统调用
%eax | Name | %ebx | %ecx | %edx | %esx | %edi |
---|---|---|---|---|---|---|
1 | sys_exit | int | - | - | - | - |
2 | sys_fork | struct pt_regs | - | - | - | - |
3 | sys_read | unsigned int | char * | size_t | - | - |
4 | sys_write | unsigned int | const char * | size_t | - | - |
5 | sys_open | const char * | int | int | - | - |
6 | sys_close | unsigned int | - | - | - | - |
边蒙边分析helloworld
现在,我们终于可以分析理解hello world的每一行代码了
- 一开始看到的为代码的入口
1
2
3
4section.text
global _start
_start: - 之后是赋值语句之前有了解过,所以知道mov是赋值语句,将逗号之后的内容,赋予逗号之前的地址。
1
2
3
4mov edx,len
mov ecx,msg
mov ebx,1
mov eax,4
那么这里就是将len赋值于edx,其他类似
查看之前的系统调用,eax为4时,系统调用为sys_write;同时ebx类型为unsigned int,暂时不知ebx赋值为1的作用;ecx被赋值msg,edx被赋值edx - 之后是已知含义为调用相关中断
1
int 0x80
之前学习单片机的时候就了解中断的概念,就是单个cpu进行正常运行时,当遇上中断触发,需要先运行终端中的内容,完成之后,再返回原本的程序继续运行
此处调用相关中断,实质内容就是参考寄存器,输出内容 - 2中的msg与len这两个常量是哪里来的呢,就是此处,即猜测出来,也提前看了后文字符串部分内容印证,知道为赋值语句
1
2
3section.data
msg db 'Hello, world!',0xa
len equ $-msg
将Hello, world!赋值给msg,暂时不了解之后的0xa的作用
将msg的长度赋值给len
参考
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 智未开笔记!