- 博客(16)
- 收藏
- 关注
原创 条件跳转的范围不够了怎么办?扩容!
1. beq的跳转范围只有1 << 12在之前的开发中遇到了beq跳转到外部的引用时出错的情况,当时跳转惊叹居然还有跳转范围这个说法,只晓得j的跳转范围比beq大,但为什么会有跳转范围这个说法,如何解决的,如果跳转的范围连j都无法满足了怎么办?本篇文章将基于android中assembler的处理方式,来看看如何处理的。上图展示了beq的跳转范围,取1~12位,跳转的有效范围最大为4096字节,也就是1024条指令。超过1024条指令的跳转,beq就无法满足了。在工具链编译的过程中还不支持
2021-05-24 16:14:43 1615
原创 vector与复制构造函数——创造了一个不可思议的结果
先分享这个可不思议的结果,再来分析为什么会这样。情况是:实例化Branch类为bat1,给bat1的构造函数传递参数,将private的成员变量m_a,m_b,m_c分别赋值为1,2, 3。通过容器emplace_back传参后,调用构造函数,将构造函数生成的对象存入到容器中。打印出容器的内容,此时容器branches_[0]中m_a,m_b,m_c的值为1, 2, 3。接着调用赋值构造函数,生成对象bat2。在构造函数中定义m_a,m_b,m_c的值为4, 5, 6。再通过容器emplace_back
2021-05-21 15:08:43 1102 1
原创 c++多线程一:什么是多线程
多线程与多核无论是手机还是pc,都存在着多核,多核cpu可以同时处理多种事情。尤其是存在着线程可能会阻塞的情况下,使用多线程对于效率有很高的帮助,举个形象的例子,在烧开水的时候这段时间如果是单线程执行,明明在烧开水的时候可以完成其他事情,但是没有办法,单线程只能按照事情的顺序一件件取做。目前网络上关于c++多线程相关的教程和讲解并不是很多,甚至在c++的绝大多数书籍中都没有涉及到相关知识的讲解。因为对于多线程的使用一般都集中在java等更加高级的语言中,这些语言一般也会封装的很友好,像在java中
2021-06-07 09:47:07 344
原创 c/c++中的static关键字
C语言中static变量在c语言中,static关键可以用来修饰变量,作用如下:#include<stdio.h> void count(){ static int num = 0;// int num = 0; num++; printf("%d ", num);}int main(){ for(int i=0; i < 5; i++){ count(); } printf("\n"); return
2021-05-31 10:39:49 182
原创 Android:assembler_test.cc是如何进行测试的
上一篇条件跳转的范围不够了怎么办?扩容!讲述了跳转在汇编层面跳转指令是如何生成机器码的,以及当条件跳转的13位跳转空间不够的时候,是如何依托auipc和jalr来实现32位的条件跳转的。接下来我们来分析一下安卓中如何使用test.cc对编写的assembler进行测试。此处仅对扩容跳转进行测试。测试源码TEST_F(AssemblerRiscv64Test, LongBeq) { riscv64::Riscv64Label label; __ Beq(riscv64::A0, riscv64::
2021-05-31 10:29:09 263
原创 内存屏障
一、什么是内存屏障?首先根据一个简单的例子来看一下为什么需要内存屏障public class MemoryBarrier{ private static boolean initFlag = false; public static void main(String[] args) throws InterruptedException{ new Thread(() -> { System.out.println("waiting dat
2021-05-24 09:12:31 415
原创 从strcpy函数移植学riscv汇编
一、如何将strcpy函数从arm移植到riscv一个的strcpy函数,如果用c语言实现,只有以下几行代码,其目的是实现字符串的拷贝。但是如果需要拷贝的量很大的时候一个个拷贝效率可想而知是非常低的。所以在arm对于strcpy函数的实现是比较复杂的,涉及到需要拷贝的字节较少不对齐的情况,拷贝的字节数较多需要对齐等情况。char * strcpy(char *dst,const char *src) //[1]{ assert(dst != NULL && src != N
2021-05-24 09:11:33 729
原创 mips中关于j跳转和b跳转
先来看源码,该函数是mips64实现的对于aget_object的汇编实现:%def op_aget_object(): /* * Array object get. vAA <- vBB[vCC]. * * for: aget-object */ /* op vAA, vBB, vCC */ .extern artAGetObjectFromMterp lbu a2, 2(rPC)
2021-05-21 16:17:11 3083 1
原创 shell脚本实现开机时间统计
1. 场景:需要多次数统计Android的开机时间在移植完汇编解释执行后,需要对比c++的解释执行和汇编解释执行这两种情况下的开机时间。一开始采用的比较土的自己掐秒表方法,但一方面需要统计的次数比较多,另一方面自己掐秒表太费时也太耗精力,如何使用shell脚本实现自己开机,统计。首先通过查询,android启动成功的标志为Android字样出现,在riscv汇编解释执行的情况下在logcat中会生成I ActivityTaskManager: Displayed com.eswin.tv.launche
2021-05-21 16:13:01 892 1
原创 Assembler如何把跳转汇编变成机器码的(四)
步骤三:计算向前跳转的targetbeq5为向前跳转,此时label1->pos为-8-8,其中-8位Bind(label1)到beq4结束为止的偏移量。这个时候beq5调用Bcond的时候,uint32_t target = label->IsBound() ? GetLabelLocation(label) : Branch::kUnresolved;pos为负数,调用GetLabelLocation,其源码如下:uint32_t Riscv64Assembler::GetLabelL
2021-05-21 15:30:32 487
原创 Assembler如何把跳转汇编变成机器码的(三)
#步骤2: 计算target1.Bind(Label1)计算出属于label1跳转的targetBind函数完成了两个工作,第一个计算出Bind之前,该label的所有跳转的target,第二个是记录此时Bind(label)的地址,在接下来跳转到该label的时候可以直接计算出target。来看源码:void Riscv64Assembler::Bind(Riscv64Label* label) { CHECK(!label->IsBound()); uint32_t bound_
2021-05-21 15:29:51 153
原创 Assembler如何把跳转汇编变成机器码的(二)
步骤一:对跳转指令进行占位##1. 跳转指令是没有办法直接生成机器码的beq a0 a1 1f该指令的意思是如果a0寄存器的值等于a1寄存器,那么就跳转到向下1:处的地址。对于机器来说,机器暂时还不知道1f在哪,因为尚未执行到1f,这是一个未知的地址。在这种情况下,beq暂时还没办法生成机器码。那么如何处理呢?先做标记,然后占位。由于并不知道要跳往哪里,先把变量目的地址target设置为一个极大值,然后标记,标记是指记录下此时beq的地址,位于buffer的哪里,并且占据beq所需要的长度。对于b
2021-05-21 15:29:04 349
原创 Assembler如何把跳转汇编变成机器码的(一)
#1. java是如何变成机器码的?在dex2oat阶段,java生成的dex字节码经过trycompile阶段,调用code_generator_riscv64.cc,通过字节码对应的函数调用相应的汇编,汇编代码通过assembler来实现了机器码的生成。在dex2oat阶段并不是所有的dex字节码都可以编译成机器码,有些字节码只可以做到优化,只能放在解释执行中取执行。现在的操作系统为了优化开机时间和打开时间,也不会过分地将字节码变成机器码,而是留到解释执行中进行runtime处理。解释
2021-05-21 15:26:31 821 2
原创 动态链接三:延时绑定
PLTPLT是一种表结构,能够帮助我们触发符号地址的计算以及跳转到正确的符号地址上,PLT一方面可以帮助我们借用jmp指令可以实现更远范围的跳转(邓凡平P67),在程序中如果使用条件判断跳转的话,跳转到外部函数的跳转范围可能会不够。另一方面可以帮助我们实现延时绑定。结合2.3章的内容我们来分析一下位置有关码,位置无关码,plt和got的情况。接着2.3中的反汇编代码来我们来看一下main是如何通过plt调用printf的绝对地址来实现延时绑定的:Disassembly of section .plt:
2021-05-21 15:07:36 664
原创 动态链接二:关于动态链接与静态链接
关于动态链接为什么要使用动态链接呢?因为静态链接对计算机的内存和磁盘的空间浪费非常严重,特别是多进程操作系统情况下,程序内部除了printf,scanf,strlen这样的公共库函数,还有其他的库函数和辅助数据结构。在linux系统中,一个普通c语言静态库至少会在1MB以上,如果机器中运行多个这样的程序,浪费的磁盘空间是非常大的。比如:程序program1和program2分别包含program1.o和progarm2.o,并且他们公用lib.o这个公共模块。在静态链接的情况下,因为progarm1和pr
2021-05-21 15:06:39 842
原创 动态链接一:ELF文件格式
ELF是Executable and Linkable Format的缩写,Linkable:可链接,表示ELF文件是链接工作的重要参与者,Excutable:可执行,表示ELF将参与程序的执行工作,包括二进制程序的运行和.so文件的加载。图1.1 ELF文件中的Linking View和Execution View示意图通常情况下我们常见的ELF文件有:c/c++文件编译后得到的.o文件,动态库.so文件,.o和.so文件链接后得到的二进制可执行文件也是ELF文件。Art生成的可执..
2021-05-21 15:04:51 351
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人