keil 生成反汇编文件
额外知识补充
MOVS 和 MOV 的区别,还是有ADDS 和ADD
在CPU中有一种特殊的寄存器, 在ARM中称为状态寄存器, 即CPSR寄存器, 该寄存器每一位都有专门的意义
movs会改变状态标记位, 意思就是发生相应的情况会改变状态寄存器对应的值
- 长度 32bit
- CPSR的低8位(包括I、F、T和M[4:0])称为控制位,程序无法修改,除非CPU运行于特权模式下,程序才能修改控制位!
- 8~27位是保留位,方便后期扩展
- N、Z、C、V均为条件码标志位。它们的内容可被算术或逻辑运算的结果所改变,并且可以决定某条指令是否被执行!
keil 生成反汇编和bin文件
参考: https://www.cnblogs.com/zhugeanran/p/8493058.html
填写指令:
- 生成汇编指令:
fromelf --text -a -c --output=all.dis Objects\StepMonitor.axf
其中 "all.dis" 和 "Objects\StepMonitor.axf" 都是相对于 ".uvprojx" 所在目录而言的 - 生成烧写bin文件
fromelf --bin --output=test.bin Objects\StepMonitor.axf
其中,烧写bin文件需要使用到STM32CubeProgrammer
指令集
arm 架构下的汇编指令集(stm32)
EQU 给数字常量名取一个符号名,相当于C语言中的define
AREA 汇编一个新的代码段或者数据段
SPACE 分配内存空间
PRESERVE8 当前文件栈需按照 8 字节对齐
EXPORT 声明一个标号具有全局属性,可被外部的文件使用
DCD 以字为单位分配内存,要求 4 字节对齐,并要求初始化这些内存
PROC 定义子程序,与 ENDP 成对使用,表示子程序结束
IMPORT 声明标号来自外部文件,跟 C 语言中的 EXTERN 关键字类似
B 跳转到一个标号
END 到达文件末尾 ,文件结束
IF,ELSE, ENDIF 汇编条件分支语句,跟 C 语言的 if else 类似
MRS 加在特殊功能寄存器的值到通用寄存器
MSR 存储通用寄存器的值到特殊功能寄存器
CBZ 比较,比较结果为0就转移
CBNZ 比较,比较结果非0就转移
ADR 从存储器中加载字到寄存器中 l 是 LDR[伪指令] 加载一个立即数或者一个地址值到一个寄存器。例如:ldr rd, = lable 如果 label 是立即数,那 Rd 等于立即数,如果 labe一个标识符,比如指针,那存到 Rd 的就是 label 这个标识符的地址
LDM 多数据加载,从一片连续的空间加载多个字到若干寄存器
LDR 加载字到寄存器
LDRD 从连续的地址空间加载双字(64位整数)到两个寄存器
LDRH 从存储器中加半字到一个寄存器中
LDRB 从存储器中加载字节到寄存器中
STR 把一个寄存器按字存储到存储器中
STRH 把一个寄存器存的低【半】字存储到存储器中
STRB 把一个寄存器的低字节存储到存储器中
LDMIA 将多个字从存储器加载到 CPU 寄存器,先操作,指针在递增。
SDM 存储若干寄存器中的字加载到一片连续的地址空间中
STMDB 将多个字从 CPU 寄存器存储到存储器,指针先递减,再操作
ORR 按位或
BX 直接跳转到由寄存器给定的地址
BL 跳转到 标号对应的地址,并且把跳转前的下条指令地址保存到 LR
BLX 跳转到由寄存器 REG 给出的的地址,并根据 REG 的 LSB 切换处理器状 态 , 还 要 把 转 移 前 的 下 条 指 令 地 址 保 存 到 LR 。 ARM(LSB=0),Thumb(LSB=1)。CM3 只在 Thumb中运行,就必须保证 reg 的 LSB=1 否则一个fault 打过来
PC 程序寄存器,保留下一条CPU即将执行的指令
LR 连接返回寄存器,保留函数返回后,下一条应执行的指令
PUSH 压栈操作, eg: PUSH {r4-r7,lr}, 将r4-r7的值进行压栈操作
MOVS 设置寄存器r0的值为0, eg: MOVS r0,#0
SUB 减 SUB r0,r4,#0x10; r0 = r4 + 16;
ADD 加 同 SUM
SDIV 除 (SDIV r0,r4,r0) r0 = r4/r0
CMP 比较指令
ASRS 左移 eg:ASRS r4,r4,#16; r4 = r4 >> 16
LSLS 右移位
SXTB 带符号(Signed)扩展一个字节(Byte)到 32位
SXTH 带符号(Signed)扩展一个半字(Half)到 32位
UXTB 无符号(Unsigned)扩展一个字节(Byte)到 32位
UXTH 无符号(Unsigned)扩展一个半字(Half)到 32位
LSL 右移位操作 (ADD r0,r4,r4,LSL #1), 意思就是 r0 = r4*3 = r4+r4<<1;
x86 寄存器说明
8个通用寄存器:EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP
1个标志寄存器:EFLAGS
6个段寄存器:CS、DS、ES、FS、GS、SS
5个控制寄存器:CR0、CR1、CR2、CR3、CR4
8个调试寄存器:DR0、DR1、DR2、DR3、DR4、DR5、DR6、DR7
4个系统地址寄存器:GDTR、IDTR、LDTR、TR
其他寄存器:EIP、TSC等。
32位: EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP
16位: AX, BX, CX, DX, SI, DI, SP, BP
8 位: AH, AL, BH, BL, CH, CL, DH, DL
通用寄存器说明
EAX:累加器(Accumulator), 它的低16位即是AX,而AX又可分为高8位AH和低8位AL。EAX是很多加法乘法的缺省寄存器,存放函数的返回值,用累加器进行的操作可能需要更少时间,在80386及其以上的微处理器中可以用来存放存储单元的偏移地址。AX寄存器是算术运算的主要寄存器。
EBX:基地址寄存器(Base Register), 它的低16位即是BX,而BX又可分为高8位BH和低8位BL。主要用于在内存寻址时存放基地址。
ECX:计数寄存器(Count Register),它的低16位即是CX,而CX又可分为高8位CH和低8位CL。在循环和字符串操作时,要用它来控制循环次数;在位操作 中,当移多位时,要用CL来指明移位的位数;是重复(REP)前缀指令和LOOP指令的内定计数器。
EDX:数据寄存器(Data Register),它的低16位即是DX,而DX又可分为高8位DH和低8位DL。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址;且总是被用来放整数除法产生的余数。
ESI/EDI:分别叫做源/目标索引寄存器(Source/Destination Index Register),它们的低16位分别是SI、DI。它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串。此外,它们又作为通用寄存器可以进行任意的常规的操作,如加减移位或普通的内存间接寻址。
EBP/BSP:分别是基址针寄存器(Base Pointer Register)/堆栈指针寄存器(Stack Pointer Register),低16位是BP、SP,其内存分别放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶/底部。主要用于存放堆栈内存储单元的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。指针寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。并且规定:BP为基指针(Base Pointer)寄存器,用它可直接存取堆栈中的数据;SP为堆栈指针(Stack Pointer)寄存器,用它只可访问栈顶。在32位平台上,ESP每次减少4字节。EBP最经常被用作高级语言函数调用的"框架指针"(frame pointer),EBP 构成了函数的一个框架,在C++反汇编中EBP通常是局部变量、传进来的参数。这里要注意在intel系统中栈是向下生长的(栈越扩大其值越小,堆恰好相反)。在通常情况下ESP是可变的,随着栈的生长而逐渐变小,而ESB寄存器是固定的,只有当函数的调用后,发生入栈操作而改变,在函数执行结束之后需要还原。
x86 汇编指令,这里只整理常用的, 方便后期查询
%rax 一般用作累加器(Accumulator)
%rbx 一般用作基址寄存器( Base )
%rxc 一般用来计数( Count )
%rdx 一般用来存放数据( Data )
%rsi一般用作源变址( Source Index )
%rdi 一般用作目标变址( DestinatinIndex )
%rbp 一般用作基址指针( Base Pointer )
%rsp 一般用作堆栈指针( Stack Pointer )
MOV 传送字或字节.
MOVSX 先符号扩展,再传送.
MOVZX 先零扩展,再传送.
PUSH 把字压入堆栈.
POP 把字弹出堆栈.
PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
BSWAP 交换32位寄存器里字节的顺序
XCHG 交换字或字节.(至少有一个操作数为寄存器,段寄存器不可作为操作数)
CMPXCHG 比较并交换操作数.(第二个操作数必须为累加器AL/AX/EAX)
XADD 先交换再累加.(结果在第一个操作数里)
XLAT 字节查表转换.----BX指向一张256字节的表的起点,
AL为表的索引值(0-255,即0-FFH);
返回AL为查表结果.([BX+AL]->AL)
IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )
输入输出端口由立即方式指定时,其范围是 0-255;
由寄存器 DX 指定时,其范围是 0-65535.
LEA 装入有效地址.例: LEA DX,string ;把偏移地址存到DX.
LDS 传送目标指针,把指针内容装入DS.例: LDS SI,string ;把段地址:偏移地址存到DS:SI.
LES 传送目标指针,把指针内容装入ES.例: LES DI,string ;把段地址:偏移地址存到ES:DI.
LFS 传送目标指针,把指针内容装入FS.例: LFS DI,string ;把段地址:偏移地址存到FS:DI.
LGS 传送目标指针,把指针内容装入GS.例: LGS DI,string ;把段地址:偏移地址存到GS:DI.
LSS 传送目标指针,把指针内容装入SS.例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
LAHF 标志寄存器传送,把标志装入AH.
SAHF 标志寄存器传送,把AH内容装入标志寄存器.
PUSHF 标志入栈.
POPF 标志出栈.
PUSHD 32位标志入栈.
POPD 32位标志出栈.
ADD 加法.
ADC 带进位加法.
INC 加 1.
AAA 加法的ASCII码调整.
DAA 加法的十进制调整.
SUB 减法.
SBB 带借位减法.
DEC 减 1.
NEG 求反(以 0 减之).
CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).
AAS 减法的ASCII码调整.
DAS 减法的十进制调整.
MUL 无符号乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),
IMUL 整数乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),
AAM 乘法的ASCII码调整.
DIV 无符号除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).
IDIV 整数除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).
AAD 除法的ASCII码调整.
CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)
CWD 字转换为双字. (把AX中的字的符号扩展到DX中去)
CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去)
CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)
DS:SI 源串段寄存器 :源串变址.
ES:DI 目标串段寄存器:目标串变址.
CX 重复次数计数器.
AL/AX 扫描值.
D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
Z标志 用来控制扫描或比较操作的结束.
AND 与运算.
OR 或运算.
XOR 异或运算.
NOT 取反.
TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果).
SHL 逻辑左移.
SAL 算术左移.(=SHL)
SHR 逻辑右移.
SAR 算术右移.(=SHR)
ROL 循环左移.
ROR 循环右移.
RCL 通过进位的循环左移.
RCR 通过进位的循环右移.
以上八种移位指令,其移位次数可达255次.
移位一次时, 可直接用操作码. 如 SHL AX,1.
移位>1次时, 则由寄存器CL给出移位次数.
如 MOV CL,04 SHL AX,CL
LOOP CX不为零时循环.
LOOPE/LOOPZ CX不为零且标志Z=1时循环.
LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.
JCXZ CX为零时转移.
JECXZ ECX为零时转移.
DW 定义字(2字节).
PROC 定义过程.
ENDP 过程结束.
SEGMENT 定义段.
ASSUME 建立段寄存器寻址.
ENDS 段结束.
END 程序结束.
CLC 进位位置0指令
CMC 进位位求反指令
STC 进位位置为1指令
CLD 方向标志置1指令
STD 方向标志位置1指令
CLI 中断标志置0指令
STI 中断标志置1指令
NOP 无操作
HLT 停机
WAIT 等待
ESC 换码
LOCK 封锁
JE 指令跳转
x86 如何生成汇编
- gcc -S,生成文件为
.s
后缀名 - objdump -d [编译的二进制文件,如a.out], 反汇编,二进制文件和汇编是可以相互转化的
本文来自博客园踩坑狭,作者:韩若明瞳,转载请注明原文链接:https://www.cnblogs.com/han-guang-xue/p/16525292.html