上篇文章咱们初步认识了nasm汇编器,使用一个&34;的程序描写编译运行的进程,需要注意的是我在此处描写不会以学术的方式做严格的定义,我的本意应用简单的白话描写,尽量让每一人都能简单理解这些概念以及实现。
术语以及概念
第一篇文章从整体上讲述了一个汇编程序运行的进程,这里面包括了大量的知识,不了解这些知识多是浏览者有些茫然,咱们在这里扼要的描写文章中触及的术语以及概念。文章源自微观生活(93wg.com)微观生活-https://93wg.com/4354.html
存放器
存放器是处理器内部的存储单元,处理器加载内存单元的数据通常很慢,处理器在其内部树立一个一个叫存放器的内部处理单元,加速CPU的执行效力,通常内存单元都需要加载到存放器中处理。文章源自微观生活(93wg.com)微观生活-https://93wg.com/4354.html
小端&大端
处理器以存储内存单元不同的布局区别大端以及小端序。通常咱们可以将内存想象为一个巨大的数组,这个数据存储了数据,索引叫做地址,这个数据每一一个单元存储了一个字节。文章源自微观生活(93wg.com)微观生活-https://93wg.com/4354.html
小端序文章源自微观生活(93wg.com)微观生活-https://93wg.com/4354.html
在小端序中存储数据是依照从大到小的存储方式寄存,也就是说位于高位的寄存在高地址内存单元,位于低位的寄存在低地址内存单元。文章源自微观生活(93wg.com)微观生活-https://93wg.com/4354.html
比如举个例子,在存储AA 56 AB FF4个字节的数据,在内存中表现为:文章源自微观生活(93wg.com)微观生活-https://93wg.com/4354.html
0 FF
1 AB
2 56
3 AA
第一列是内存单元,第二列是寄存的数据,高字节AA寄存在内存地址为3的地址上。Intel采取的存储是小端序。文章源自微观生活(93wg.com)微观生活-https://93wg.com/4354.html
大端序文章源自微观生活(93wg.com)微观生活-https://93wg.com/4354.html
以及小端序相反,高位的数据寄存在高地址,低位的数据寄存在低地址。在存储AA 56 AB FF4个字节的数据,在内存中表现为:文章源自微观生活(93wg.com)微观生活-https://93wg.com/4354.html
0 AA
1 56
2 AB
3 FF
大端序更为相符人类的浏览方式。文章源自微观生活(93wg.com)微观生活-https://93wg.com/4354.html
系统调用
系统调用是操作系统为用户程序提供的一组系统API,这些API屏蔽了底层硬件以及实现的繁杂性。而操作系统通常就是应用这些API提供了高层次的抽象,你可以在系统调用
中找到所有的系统调用。
栈
咱们大部份的利用程序都是由栈来实现的,尤其是过程以及线程的模型,参数传递等功能都是应用其实现。
这个以及咱们程序中定义的栈抽象结构不是一回事情,但从本色上都是一个先进后出的队列。底层硬件为栈结构提供了很大的支持以及优化,RSP,SS,RIP。咱们后面会详细描写这个结构。
节
每一一个汇编程序通常都是有多个节组成,最多见的节有:
- data 已经被初始化的变量以及常量通常存在这里
- bss 没有被初始化的常量寄存在这里
- text 指令代码寄存之处
通用存放器
在X86_64中由16个通用存放器rax, rbx, rcx, rdx, rbp, rsp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15。
这里不可能描写所有的术语以及概念,咱们会跟着进一步的加深,来描写遇到的概念以及专业术语。
数据类型
在汇编语言中,有字节,字,双字doublewords,4个字节),四字以及8字。
咱们这里描写的都是整数类型,通常有两个整数类型:
- 无符号
无符号类型的数据少了一个位表示符号位类型规模字节0 to 字0 to 双字0 to 4字0 to - 有符号
有符号的使用一名表示符号位,唆使正负类型规模字节-2^7 to 字-2^5 to 双字–2^31 to 4字-2^63 to
节
就像咱们前面所说的,一个汇编程序有多个节组成,它可以表示初始化的数据节,代码节以及未初始化的节。一个节通常表示了一段连续的内存单元,由编译器进行分配。
例如,咱们声明初始化的数据:
section .data
num1: equ 100
num2: equ 50
msg: db &34;, 10
很显明,这段程序声明了3个变量num1,num2以及msg,它们的值分别是100,50以及&34;。或许您会问msg的变量为何以及其他不同样,这是由于在NASM中支撑一些伪指令,它们可以帮助简化咱们的开发。在NASM中:
- DB, DW, DD, DQ, DT, DO, DY 以及 DZ - 用于声明初始化数据,例如
;; Initialize word to 0x12 0x34;; Initialize 4 bytes 1h, 2h, 3h, 4h
db 0x01,0x02,0x03,0x04
dw 0x1234
- RESB, RESW, RESD, RESQ, REST, RESO, RESY 以及 RESZ - 用于声明未初始化的数据
- INCBIN - 引用外部二进制文件
- EQU - 定义常量,例如:
;; now one is 1
one equ 1
- TIMES - 重复执行指令以及数据
算术操作
下面列出了部份算术操作指令:
助记符 |
描写 |
ADD |
加 |
SUB |
减 |
MUL |
无符号乘 |
IMUL |
有符号乘 |
DIV |
无符号除了 |
IDIV |
有符号除了 |
INC |
自增 |
DEC |
自减 |
NEG |
取负 |
有些指令您会在这章看到,有些会在后续的章节里面描写到。
节制流
通常咱们在高档语言中会看到扭转指令执行的顺序,同理在汇编语言中也有。咱们下面将重点描写汇编语言的节制流。
cmp指令执行两个操作数比较,cmp的功能至关于减法指令,只是对操作数之间运算比较,不保留结果。cmp指令执行后,将对标志存放器发生影响。例如:
;; compare rax with 50
cmp rax, 50
cmp指令将rax存放器中的内容同当即操作数50比较,在比较的进程中,cmp其实不影响操作数,它将会将比较结果影响标志存放器。通过前提转移指令,咱们就能够到达指令跳转的目的,咱们可使用下列前提挑战指令:
助记符 |
描写 |
JE |
如果相等 |
JZ |
如果为0 |
JNE |
如果结果不相等 |
JNZ |
如果结果不为0 |
JG |
如果第一个操作数大于第二个 |
JGE |
如果第一个操作数大于等于第二个 |
JA |
以及JG同样,区分是做无符号比较 |
JAE |
以及JGE同样,区分是做无符号比较 |
如果咱们但愿编写一个相似C语言中if/else的语句:
if {
exit;
} else {
right;
}
那么咱们可以这样写:
;; compare rax with 50
cmp rax, 50
;; perform .exit if rax is not equal 50
jne .exit
jmp .right
这里使用了无前提转移指令,语法如下:
JMP label
例如:
.exit:_start:
;; ....
;; do something and jump to .exit label
;; ....
jmp .exit
mov rax, 60
mov rdi, 0
syscall
这里咱们可以在**_start**标签后面添加一些指令,这样这些指令被执行完后,程序会直接跳转到.exit执行退出程序。
这段程序GCC默许插入到咱们编写的C代码中,这样咱们就不需要显示的调用exit系统调用了,编译器自动添加退出程序。
无前提调转指令通经常使用在循环中。例如,咱们有一个标签,在这个标签后有一些执行代码,如果前提不知足,咱们可以跳转到标签处执行,直到前提知足。后面会有循环的案例代码。
**注意:**一般是了机能的斟酌,编译器会做一些优化,尽可能使用前提转送指令。
例子
咱们以一个例子收场本章,咱们使用两个整数,将两个数相加,然后同指定的数进行比较,如果指定的数等于两个数的以及,那么打印一些数据,否则,退出程序。
section .text
global _start
;; entry point 咱们在这个章节中更为详细地了解了汇编程序中一个概念以及术语帮助咱们后面课程的学习。以一个例子收场了本章,对上一章的知识有一个更为深入的认识以及了解。
以上就是微观生活(93wg.com)关于“初识x86_64汇编-基础知识”的详细内容,希望对大家有所帮助!
section .data
; Define constants
num1: equ 100
num2: equ 50
; initialize message
msg: db &34;
_start:
; set num1&39;s value to rbx
mov rbx, num2
; get sum of rax and rbx, and store it&34;Sum is correct\\n"。
总结
评论