平台

汇编语言是跟平台相关的,使用哪个平台的 GCC,生成的汇编代码就是哪个平台的。

x86 平台:

gcc -S simple.i -o simple.s

ARM 平台:

arm-linux-gcc -S simple.i -o simple_arm.s

所以,编译四步骤:预处理、编译、汇编、链接,第一步预处理在各个平台上都是一致的,当然库文件内容不同也会产生差异;从第二步编译,就真正开始不同了。

参考:

GCC基本使用

x86汇编快速入门

.text

汇编 .section 和 .text 解释

.LFB0

c - 编译器生成的汇编代码中的 .LFB .LBB .LBE .LVL .loc 是什么

#define FUNC_BEGIN_LABEL  "LFB"
#define FUNC_END_LABEL    "LFE"
#define BLOCK_BEGIN_LABEL "LBB"
#define BLOCK_END_LABEL   "LBE"
ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);

LFBLFE 在函数的开头和结尾生成

%rbp

rbp 是寄存器的名字

AT&T 格式的汇编,寄存器之前要加 %

rbp:register of base pointer 堆栈基指针寄存器(64位环境用 rbp 表示,32 位环境用 ebp 表示)

汇编 rbp_汇编入门

rip/eip/rbp/ebp

函数调用过程中栈到底是怎么压入和弹出的? 一图胜千言

草图

堆栈

eax、ebx、ecx、edx

首先介绍我们会经常看到的一些寄存器: 4个数据寄存器(EAX、EBX、ECX和EDX) 2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP)

32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。对低16位数据的存取,不会影响高16位的数据。这些低16位寄存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。 4个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每个寄存器都有自己的名称,可独立存取。程序员可利用数据寄存器的这种“可分可合”的特性,灵活地处理字/字节的信息。

那么如何理解eax,ax,al(ah)之间的关系呢? 专业点可以这样解释:Eax是32位寄存器,ax是16位寄存器,al(ah)是八位寄存器。 那么eax存储的数据就是ax的两倍,ax是al(ah)的两倍。 Eax可以存储的数字是DWORD(双字)ax存储的是WORD(字)AL(AH)存储的是BYTE(字节),那么为什么又有AH和AL呢,我们可以这样理解,AX=AH+AL,AH存储的是AX的高8位数据,AL存储的是AX的低八位数据。H这里就是HIGH,L就是LOW. 假设eax是0x64636261;那么ax就是eax的低十六位,也就是0x6261;Al是0x61;AH是0x62。

其他ebx,ecx,edx也有类似的bx,bl,bh等对应的寄存器,原理和上面相同。

在用途方面,他们有各自默认的用途:

  • Eax用来保存所有API函数的返回值。

  • 寄存器AX和AL通常称为累加器(Accumulator),用累加器进行的操作可能需要更少时间。累加器可用于乘、除、输入/输出等操作,它们的使用频率很高;

  • 寄存器BX称为基地址寄存器(Base Register)。它可作为存储器指针来使用;

  • 寄存器CX称为计数寄存器(Count Register)。在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数;

  • 寄存器DX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。

由于存储的数据大小关系,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址, 32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果,而且也可作为指针寄存器,所以,这些 32 位寄存器更具有通用性。(什么是基址,什么是变址以后会说到)

参考:

eax …edi esp ebp寄存器简介(转)

edi、esi

2个变址和指针寄存器(ESI和EDI) 32位CPU有2个32位通用寄存器ESI和EDI。其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响高16位的数据。

esp、ebp

这两个指针寄存器都和“栈”这个神秘的东东有关,

那么ESP和EBP指的分别是什么呢?

  • ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
  • EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。

重点内容:记住eax一般用来保存函数的返回值,esp是栈顶指针寄存器,ebp是栈底指针寄存器,其它的就当通用寄存器。

.global

在汇编语言中导出符号名用 global 关键字,global 将符号导出为全局属性,对程序中的所有文件可见,这样其他外部文件中也可以引用被 global 导出的符号啦,无论该符号是函数,还是变量。

下面这个示例是为了将 _start 导出为全局符号,为的是给链接器用的。

——《操作系统真象还原》

.global _start

_start:
    jmp _start

STM32 汇编

参考:基于LPC2000和STM32F103的视频教学(ARM)(汇编详细)

语法

简单的ARM程序

  1. 使用 “;” 进行注释,单行注释。汇编没有多行注释
  2. 文件名以“.S”结尾,英特尔使用“.asm”
  3. 转向 process on

大佬

汇编语言入门教程 ——阮一峰

汇编 ——csdn shenmingik

参考

汇编 —— 函数 介绍了什么情况下只需要用寄存器就行了,什么情况下需要用到内存。正和我意。