打印
[开发生态]

keil C对lib封装库反汇编成C语言

[复制链接]
102|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
rosemoore|  楼主 | 2024-6-24 11:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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], 反汇编,二进制文件和汇编是可以相互转化的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

1197

帖子

2

粉丝