精华内容
下载资源
问答
  • 如题,通过C语言代码调用汇编实现的函数 1.创建两个文件:compare.S和main.c compare.S .section .text .globl compare_data compare_data: cmp x0, x1 csel x0, x0, x1, hi //若x0>1则返回x0, 否则返回x1 ret...

    如题,通过C语言代码调用汇编实现的函数

    1.创建两个文件:compare.S和main.c

    compare.S

    .section .text
    .globl compare_data
    compare_data:
            cmp x0, x1
            csel x0, x0, x1, hi //若x0>1则返回x0, 否则返回x1
            ret
    

    main.c文件

    #include <stdio.h>
    
    extern int compare_data(int a, int b); //extern导入compare_data函数声明
    
    int main()
    {
            int val;
    
            val = compare_data(5, 6); //调用汇编函数
    
            printf("big data: %d\n", val);
    }
    

    2.编译

    aarch64-linux-gnu-gcc -o main main.c compare.S --static -g
    

    3.运行

    # ./main
    big data: 6
    
    展开全文
  • 如题,有时为了提高部分代码运行性能,可以将部分C代码实现,用汇编改写(自己编写常比编译器优化效果更好) 1.先看案例: #include <stdio.h> static int compare_data(int a, int b) { int val; asm ...

    如题,有时为了提高部分代码运行性能,可以将部分C代码实现,用汇编改写(自己编写常比编译器优化效果更好)

    1.先看案例:

    
    #include <stdio.h>                                                                                          
    
    static int compare_data(int a, int b)
    {
    	int val;
    	__asm__ __volatile__ (
    	    "cmp %1, %2\n"
    	    "csel %0, %1, %2, hi\n"
    	    : "+r" (val)
    	    : "r" (a), "r" (b) 
    	    : "memory");
    
    	return val;
    }
    
    int main()
    {
    	int val;
    
    	val = compare_data(5, 6); 
    	printf("big data: %d\n", val);
    
    	val = compare_data(6, 4); 
    	printf("big data: %d\n", val);
    	
    	return 0;
    }            
    

    编译运行:

    aarch64-linux-gnu-gcc -o main main.c --static -g
    # ./main
    big data: 6
    big data: 6
    

    2.语法解析:

    C/C++中嵌入汇编,常用格式如下:

    __asm__ [__volatile__] ( assembler template 
               : [output operand list]             /* optional */
               : [input operand list]              /* optional */
               : [clobbered register list]         /* optional */
               );
    

    关键字__asm__:其实也可以写成“asm”。但是“asm”并不是所有版本的GCC编译器都支持的,而且可能有命名冲突问题,所以用“asm”的话,兼容性更好。

    关键字__volatile__:也可以写“volatile”,理由同上;__volatile__是可选的,作用是禁止编译器对后面汇编指令再进行优化。一般自己写的汇编,考虑性能,已经做过优化,编译器再优化的话,可能效果反而更差,所以通常还是带上这个关键字;

    括号里:是真正的汇编代码,主要有四部分组成,第一部分是具体的汇编代码,是必须的;其他三个为辅助参数,可选;各部分之间用冒号“:”分割,即使参数为空,也要加冒号;

    2.1 assembler template:

    所有汇编代码必须用双引号括起来,如果多行汇编代码,每一条语句都要用双引号括起来,代码后面加上换行符("\n"或"\n\t"),具体形式如下:

    __asm__ __volatile__ ( "instruction 1\n\t" 
               "instruction 2\n\t"
               ......
               "last instruction"
               );
    

    注:即使一行汇编代码也没有,也要传入空字符串"",否则会报错;

    2.2 [output/input operand list] :输出/入参数列表;

    分别对应汇编与C语言交互的C表达式,若有多个,用逗号隔开;

    在前面汇编中,还可以用"%n",直接引用后面的操作数;

    __asm__("mov %0, %1, ror #1" 
                : "=r"(result) 
                : "r"(value)
                );
    

    这里%0代表第一个操作数,result变量;
    %1代表第二个操作数,即value变量;

    操作数格式:

    每一个操作数,最多由四部分组成:

    [name]"modifier+constraint"(C expression)
    

    name:别名,可选;
    modifier:修改符,要用双引号括起来;
    constraint:限定符,要用双引号括起来;
    c表达式:用小括号括起来;

    (1)如果指定了别名的话,那在汇编模板中,引用该变量,就可以使用别名,增加可读性,例如:

    int x=10, y;
    __asm__ ("mov %[in],%[out]"
       : [out]"=r"(y)
       : [in]"r"(x)
       :
    );
    

    (2) 说说限定符,操作数在这里的作用是将C语言定义的变量与汇编中使用的变量进行一 一对应,但并不是所有的汇编指令都可以接受任何类型变量,因此汇编器需要知道这些变量到底用在什么地方,传递前做一些转换。常用限定符如下表

    限定符ARM指令集含义
    r通用寄存器
    f浮点寄存器
    m内存地址

    (3)修改符号,在限定符之前,可选,为空的话,表明该操作数是只读的。
    GCC定义了三个修改符,分别是:

    修改符含义
    =只写操作数,一般用于输出操作数中
    +可读且可写
    &寄存器只能用于输出

    如果想让一个C变量既作为输入操作数,也作为输出操作数的话,可以使用“+”限定符,并且这个操作数只需要在输出操作数列表中列出就行了。例如:

    __asm__("mov %0, %0, ror #1" 
            : "=r"(y)
            : "0"(y)
            );
    

    &”:为了避免编译器优化输出和输入使用同一个寄存器,可在输出操作数中使用“&”修改符,明确告诉编译器,代表输出操作数的寄存器一定不能使用输入操作数已经使用过的寄存器。

    2.3 修改寄存器列表

    为保持寄存器,内存数据一致性,提供三个类型

    类型作用
    r0…r15告诉编译器汇编代码中修改了通用寄存器r0…r15
    cc告诉编译器汇编代码会导致CPU状态位的改变
    memory告诉编译器汇编代码会读取或修改内存中某个地址存放的值

    添加“memory”之后,编译器会在执行汇编代码之前,保证将保存在寄存器中,没有更新到内存中的值全部都写入到内存中。
    此列表中的每一项都要用双引号("")括起来,每项之间要用逗号(“,”)分割。

    展开全文
  • ARM所有的运算指令只能基于寄存器,所以,要先从内存Load要运算的数据到寄存器,运算完成后,再将寄存器的结果Store到内存,这两个操作相应的指令如下: 还有Mov指令,但是并不能从内存读写数据,只能是直接的一...

    内存操作指令​

    ARM所有的运算指令只能基于寄存器,所以,要先从内存Load要运算的数据到寄存器,运算完成后,再将寄存器的结果Store到内存,这两个操作相应的指令如下:

     还有Mov指令,但是并不能从内存读写数据,只能是直接的一个数(立即数),或者寄存器:

    指令不难理解,麻烦的是[addr],各种姿势,婉转百变,今天抽时间解锁一下

    寻址方式

    首先[addr]里面一定有一个寄存器,这个寄存器的值是一个内存地址,称之为Base Register,可以理解为c语言里面的一个ptr。Base Register在寻址之前或者之后都可以进行一些运算操作,操作结果可以更新到这个Base Register,也可以不更新到Base Register。具体来说,有下面几种:

    • 最简形式:Base Register模式

      可类比于:*(ptr) <-> value

      下面的x1不会变

    ldr  x0,  [x1]   /* [x1] -> x0 */
    • 带感叹号!的形式:Pre-Index寻址模式

      可类比于:*(++ptr) <-> value

      下面的x1会先更新,然后用来寻址

      典型的:入栈操作,先栈指针sp--,然后数据入栈

    str x2, [x1, x2, LSL#2]!  /* x2->[x1 + x2<<2];x1 = x1 + x2 << 2 */
    • 单纯的[REG]的形式:Post-Index寻址模式

      可类比于:*(ptr++) <-> value

      下面的x1在寻址完成后,再更新

      典型的:出栈操作,先数据出栈,然后sp++

    ldr x3, [x1], x2, LSL#2  /* x3 <- [x1]; x1 = x1 + x2 << 2 */ 
    • 其它的形式:Offset寻址模式

      可类比于:*(ptr + xxx) <->value

      下面的x1不会更新

    str x2, [x1, x2, LSL#2]  /* x2 -> [x1 + x2 << 2] */

    更多的例子

    • Pre-Index模式

    ldr   x3, [x1, #4]!
    ldr   x3, [x1, r2]!
    ldr   x3, [x1, r2, LSL#2]!
    stp   x0, x1, [sp, #-16]!  /* 入栈:sp = sp - 16;x1/x0->sp */
    • Post-index模式

    ldr   x3, [x1], #4
    ldr   x3, [x1], r2
    ldr   x3, [x1], r2, LSL#2
    ldp   x29, x30, [sp], #0x10   /* 出栈:x30/x29<sp;sp = sp + 16 */
    • Offset模式

    ldr   x3, [x1, #4]
    ldr   x3, [x1, r2]
    ldr   x3, [x1, r2, LSL#2]

    立即数

    说一下立即数,形式可以为:

    • #<immediate|symbol>

    • =<immediate|symbol>

    mov w2, #14 << 4
    bic x4, x4, #((1 << 21) - 1)

    #<immediate|symbol>的方式对位数和运算操作有限制,如果编译出错,可以换成如下的形式

    ldr <reg> =<immediate|symbol>

    =<immediate|symbol>只能用于ldr指令

    temp_var: .word 0
    ldr x1, =temp_var
    ldr x1, =0x0000000000802520

    ARM官方说明:参考链接

    图片

    展开全文
  • 这里直接采用笨叔提供的qemu工具,以及初始化代码BenOS,再添加自己的测试代码来调试ARM汇编指令。考虑版权因素,用到的工具及BenOs源码,这里不公开,有兴趣的朋友,可以去购买笨叔的教材,获取详细资料。 编译好...

    完全是方便自己查询,做个记录。

    树莓派4的SOC是ARM64, cortex A72,支持最新的ARMv8指令集,且有众多的开源资料,适合用来学习ARM64汇编,其他芯片大同小异,遇到需要,再进一步研究qemu支持的芯片;

    最新版官方qemu尚未支持树莓派4, 这里直接采用笨叔提供的qemu工具

    1.测试代码test.S

    .global _start
    _start:
            mov x1,0x80000
            mov x3,16
    
            ldr x0,[x1]
            ldr x2, [x1,#8]
            ldr x4, [x1,x3]
            ldr x5, [x1,x3,lsl #3]
    

    2. 编译

    makefile文件

    ARMGNU ?= aarch64-linux-gnu
    test.elf: test.o
            $(ARMGNU)-ld -Ttext 0x0  -o test.elf   $^
    %.o : %.S
            $(ARMGNU)-gcc  -o $@ $<  -g  -c
    clean:
            rm *.o *.elf    -f
    

    3.qemu模拟调试

    由于qemu自带gdb_server,这里用gdb来单步调试

    3.1 启动qemu

    qemu-system-aarch64 -machine raspi4 -nographic -kernel test.elf -S -s
    

    3.2 再开一个终端,启动gdb,链接qemu

    gdb-multiarch --tui benos.elf 
    

    链接gdb_server
    ```bash(gdb) target remote localhost:1234Remote debugging using localhost:1234_start () at test.S:3(gdb) b _startBreakpoint 1 at 0x80000: file test.S, line 3.(gdb) c

    ``
    查看寄存器值
    在这里插入图片描述

    3.3 用eclipse可视化环境调试

    (1).创建一个新工程test,添加带调试信息的程序test.elf,配置如下:
    在这里插入图片描述

    链接成功后,启动gdb,可以方便查看寄存器或变量值如下:
    在这里插入图片描述

    展开全文
  • arm64汇编入门

    2021-09-12 22:38:19
    那么这个时候学会一些汇编知识,利用汇编调试技巧进行调试可能会起到意想不到的效果。 学习汇编语言不只是帮助定位crash而已,学习汇编可以帮助你真正的理解计算机。毕竟CPU上跑的就是对应的指令集。 0x1 工具 ...
  • 返回 LDR汇编指令应用 LDR R0 [R1,#4] :寄存器 R1 的内容加上4形成操作数的有效地址,从而取得操作数存入寄存器 R0 中。 LDR R0,[R1,#4]!:将寄存器 R1 的内容加上 4 形成操作数的有效地址,从而取得操作数...
  • 一条汇编指令 __text:000000010333E3D4 B loc_10333EA74 对应字节码A8 01 00 14 其中,0x14是B对应的字节码,0x1A8是对应的偏移 0x10333EA74 - 0x10333E3D4 = 0x6A0 =0x1A8 * 4 这里*4推测是一条指令4个字节的...
  • IOS逆向-arm64汇编

    2021-05-23 16:44:56
    IOS逆向-arm64汇编
  • X86和ARM64部分汇编差异 x86 Mnemonic A64 Mnemonic Instruction MOVZX UXT Zero-Extend. MOVSX SXT Sign-Extend. BSWAP REV Reverse byte order. SHR LSR Logical Shift ...
  • 如题,演示汇编程调用C函数方法 1.创建两个文件 compare.c int compare_data(int a, int b) { return (a >= b) ?...编译 aarch64-linux-gnu-gcc -o main main.S compare.c --static -g 3.运行 # ./main big data: 6
  • ARM处理器的结构和指令集冯·诺依曼结构与哈佛结构哈弗结构起源于打卡纸存储程序指令, 而数据则存储在处理器,后来在嵌入式系统中沿用下来,将程序指令放在 ROM (Read Only Mem...
  • # 简述大约在半年以前,我曾经了解过协程的相关实现,也看过腾讯后台开源的协程库`libco`,对其中实现协程相关的...手机端使用的 CPU 跟单片机相差甚远,虽然我用的单片机也是 ARM 平台的,但和手机端 CPU 相比两者...
  • ARM64常用汇编

    2021-06-26 20:36:19
    ARM64取消32位的LDM, STM, PUSH, POP指令. 与之替代的是 ldr/ ldp, str/ stp ARM64里面 对栈的操作都是16进制对齐 ARM64下, 参数都是保存在x0-x7 (w0-w7) 这8个寄存器中, 如果超过这8个参数就会入栈, 函数的返回值是...
  • ARM64汇编器 (1)ARM公司官方的汇编器; (2)GNU AS汇编器:aarch64-linux-gnu-as; (3)gcc采用as作为汇编器,所以汇编码是AT&T格式; (4)AT&T格式:源于贝尔实验室; (5)ARM格式:ARM官方汇编语法; 汇编...
  • NEON是一种基于SIMD思想的ARM技术。 SIMD, Single Instruction Multiple Data,是一种单条指令处理多个数据的并行处理技术,相比于一条指令处理一个数据,运算速度将会大大提高。ARMv8 有31 个64位寄存器,1个不同...
  • arm64 ld1指令详解

    2021-12-02 10:06:22
    arm64 ld1指令详解
  • 0xfffffbdb 8528: 00000a64 andeq r0, r0, r4, ror #20 0x25,0x64,0x2E之间,0x25,0x64,的0x0A,为0x00 同样,在你的拆装地址你的字符串是 81d0: e59f0014 ldr r0, [pc, #20] ; 81ec <.text+0x11c> ... 81ec: ...
  • 环境及代码介绍环境和源码由于有时候要透彻的理解C里面的一些细节问题,所有有必要看看汇编...以ARM汇编来进行分析。使用一个启动汇编文件和一个main.c的文件,在ARM 2440板子上调试这段程序,使用JLinkExe借助jlink...
  • ARM汇编指令集

    2021-10-27 15:58:52
    ARM采用RISC架构,CPU本身不能直接读取内存,而需要先将内存中内容加载入CPU中通用寄存器中才能被CPU处理。ldr/str组合用来实现 ARM CPU和内存数据交换) 8种寻址方式 寄存器寻址 mov r1, r2(C语言中的r1=r2) ...
  • 1.下载交叉编译器 sudo apt-get install gcc-arm-linux-gnueabi 验证安装结果 dpkg -l gcc-arm-linux-gnueabi 显示如下: 2.下载qemu sudo apt-get install qemu ...3.创建测试代码hello.c ...4.运用交叉汇编器编译h
  • DATE:2021.8.15 文章目录1、arm架构64位优化基础知识2、ARMv8/AArch64 neon指令格式3、ARM相关编译参数4、查看状态标记位NZCV...  该博客已经分析了arm架构64汇编优化的入门基础知识,主要包括架构分析,寄存器,调用
  • C、C++和ARM汇编语言之间的调用本节提供一些示例,显示如何从C++调用C和汇编语言代码,以及从C和汇编语言调用C++代码。其中包括调用约定和数据类型。主要包括下面内容:·相互调用的一般规则;·C++语言的特定信息;...
  • 为什么要学ARM汇编? 不为什么。 学了ARM汇编有用吗? 没啥用 学完ARM汇编能找到工作吗? 目前流行的大型软件,没有一个是拿汇编写的,所以你觉得呢? 那你还要学ARM汇编吗? 学学吧,反正闲着也是闲着。会点...
  • 如题,用ARM汇编实现功能,在给定数组中查找最大数 .section .data //定义数据段段 .align 3 //以2^3对齐 my_data: //定义一个数据 .quad 1 .quad 2 .quad 5 .quad 8 .quad 10 .quad 12 my_data_count: //...
  • 部分ARM汇编指令解读

    2021-02-06 21:05:09
    Rt: ARM 源寄存器,要写入到 CP15 寄存器的数据就保存在此寄存器中 ; CRn: CP15 协处理器的目标寄存器; CRm: 协处理器中附加的目标寄存器或者源操作数寄存器,如果不需要附加信息就将; CRm 设置为 C0,否则...
  • 一.前言1.看一个程序:AREA TigerJohn,CODE,READONLY;声明代码段CODE32;声明为32位ARM指令ENTRY...汇编语言程序格式一个完整的ARM汇编由两部分组成:声明,实际代码段两部分组成。1.声明:在一个程序之前先要进行...
  • WORD 2个字节 DWORD 4个字节 32位 可以用Wn存储 QWORD 8个字节 64位 可以用Xn存储
  • ARM汇编基础

    2021-01-29 22:09:16
    ARM汇编 ARM处理器 指令样例分析 ARM汇编 ARM处理器 ARM 处理器一般有37个寄存器,其中包括: 31个通用寄存器,包括PC(程序计数器)在内,都是32位寄存器 6个状态寄存器,都是32位的寄存器 ARM处理器有7...
  • x86主机下运行ARM64程序的两种方式
  • ARM 1、Assembly ARM Assembly Language, 2nd Edition ARM 64-Bit Assembly Language

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 57,727
精华内容 23,090
关键字:

arm64汇编