首页
社区
课程
招聘
[翻译]]ARM汇编简介(一)ARM数据类型和寄存器
发表于: 2018-6-7 14:58 11580

[翻译]]ARM汇编简介(一)ARM数据类型和寄存器

2018-6-7 14:58
11580

在看雪上发现了一篇 ljcnaix前辈分享的教程,看雪链接如下:https://bbs.pediy.com/thread-220461.htm

Signed data types can hold both positive and negative values and are therefore lower in range.

Unsigned data types can hold large positive values (including ‘Zero’) but cannot hold negative values and are therefore wider in range.



The amount of registers depends on the ARM version. According to the ARM Reference Manual, there are 30 general-purpose 32-bit registers, with the exception of ARMv6-M and ARMv7-M based processors. The first 16 registers are accessible in user-level mode, the additional registers are available in privileged software execution (with the exception of ARMv6-M and ARMv7-M). In this tutorial series we will work with the registers that are accessible in any privilege mode: r0-15. These 16 registers can be split into two groups: general purpose and special purpose registers.

寄存器的数量取决于ARM的版本。根据ARM参考手册可知,有30个32位的通用寄存器(除了 ARMv6-M和ARMv7-M的处理器)。在本基础系列课程中,我们学习的对象是在任意特权模式下都可以访问的寄存器:R0-R15。这16个寄存器可以被分成两组:通用寄存器和特殊功能寄存器。



( 从r0到r11都是通用寄存器 )


(特殊功能寄存器,R12是IP寄存器,内部程序调用寄存器。R13,SP,堆栈指针寄存器。R14,LR,连接寄存器。R15,PC,程序计数器。CPSR,当前程序状态寄存器)


The following table is just a quick glimpse into how the ARM registers could relate to those in Intel processors.

下表是ARM寄存器和英特尔处理器的寄存器存在的相关联性的概览




R0-R12: can be used during common operations to store temporary values, pointers (locations to memory), etc. R0, for example, can be referred as accumulator during the arithmetic operations or for storing the result of a previously called function. R7 becomes useful while working with syscalls as it stores the syscall number and R11 helps us to keep track of boundaries on the stack serving as the frame pointer (will be covered later). Moreover, the function calling convention on ARM specifies that the first four arguments of a function are stored in the registers r0-r3.

R0-R12可以在通常的运算过程中用来存储临时的数据,指针(定位内存)等。以R0为例,当我们执行算数运算或者存储当前函数的返回值时,可以把R0视为累加器。系统调用发生时,R11开始生效,它存储了系统调用数值。R11作为栈指针帮助我们追踪栈的边界(稍后会讲到)。此外,ARM专用的函数调用规则规定了函数的前四个参数应该分别存贮与R0到R3中。


R13: SP(Stack Pointer). The Stack Pointer points to the top of the stack. The stack is an area of memory used for function-specific storage, which is reclaimed when the function returns. The stack pointer is therefore used for allocating space on the stack, by subtracting the value (in bytes) we want to allocate from the stack pointer. In other words, if we want to allocate a 32 bit value, we subtract 4 from the stack pointer.

R13:SP(堆栈寄存器)堆栈寄存器指向栈的栈顶。栈是内存中一块用于存储特定数据的存储区,它用于回收函数的返回值。因此,栈指针别用来在栈空间中分配出区域,如果我们想获得32位的数据空间,我们就让栈指针减去4。


R14: LR(Link Register). When a function call is made, the Link Register gets updated with a memory address referencing the next instruction where the function was initiated from. Doing this allows the program return to the “parent” function that initiated the “child” function call after the “child” function is finished.

连接寄存器,当有一处函数调用时,连接寄存器会用一处内存地址来获取更新,该地址是函数初始化的地方的下一行代码的地址。这么做可以允许“子函数”执行完毕后让程序返回到起“父函数”的起始地址。


R15: PC(Program Counter). The Program Counter is automatically incremented by the size of the instruction executed. This size is always 4 bytes in ARM state and 2 bytes in THUMB mode. When a branch instruction is being executed, the PC holds the destination address. During execution, PC stores the address of the current instruction plus 8 (two ARM instructions) in ARM state, and the current instruction plus 4 (two Thumb instructions) in Thumb(v1) state. This is different from x86 where PC always points to the next instruction to be executed.

R15:PC(程序计数器)。程序计数器会根据指令的大小,在指令被执行时自动增加。一条指令的大小在ARM状态下总是4个字节,在THUMB模式下总是2个字节。当一条分支指令正在被执行时,PC保持存贮着目标地址。当执行该指令时,PC存贮了当前指令的地址加8字节(ARM状态下的两条ARM指令), 或当前指令的地址加4字节(Thumb(V1)模式下的两条Thumb指令的大小)。和x86不同的是,x86下PC永远会指向下一条要被执行的指令。


Let’s look at how PC behaves in a debugger. We use the following program to store the address of pc into r0 and include two random instructions. Let’s see what happens.

我们来看看PC在调试器中的表现形式。我们让接下来的程序,在R0存储PC的地址,并且包含了两条随机的指令。让我们看看究竟会发生什么。


In GDB we set a breakpoint at _start and run it:

在GDB调试器中我们在 _start设置一个断点,并且运行这个程序


Here is a screenshot of the output we see first:

以下是我们首先看到的输出的截图



We can see that PC holds the address (0x8054) of the next instruction (mov r0, pc) that will be executed. Now let’s execute the next instruction after which R0 should hold the address of PC (0x8054), right?

我们可以看到,PC里保持着下一条将被执行的指令 (mov r0, pc)的地址0x8054,现在我们来执行下一条指令,并且在此之后R0应该还保持着0x8054的地址,对吗?


…right? Wrong. Look at the address in R0. While we expected R0 to contain the previously read PC value (0x8054) it instead holds the value which is two instructions ahead of the PC we previously read (0x805c). From this example you can see that when we directly read PC it follows the definition that PC points to the next instruction; but when debugging, PC points two instructions ahead of the current PC value (0x8054 + 8 = 0x805C). This is because older ARM processors always fetched two instructions ahead of the currently executed instructions. The reason ARM retains this definition is to ensure compatibility with earlier processors.

。。。真的对吗?显然错了。看看R0中的地址。当我们还预想着R0可以保持之前读取的PC值(0x8054)时,它反而储存了相对之前读取的0x8054之后的两条指令的地址。从这个地址我们可以看出,当我们直接读取PC时,它按照定义,PC指向下一条指令,但是当我们调试程序时,PC却指向当前PC值的下面两条指令的地址处(0x8054+8=0x805C)。这是因为,老款的ARM处理器总是获取当前已经执行的指令的后两条指令的地址。ARM保留着这个定义的原因是为了保证和早期处理器的兼容性。




When you debug an ARM binary with gdb, you see something called Flags:


The register $cpsr shows the value of the Current Program Status Register (CPSR) and under that you can see the Flags thumb, fast, interrupt, overflow, carry, zero, and negative. These flags represent certain bits in the CPSR register and are set according to the value of the CPSR and turn bold when activated. The N, Z, C, and V bits are identical to the SF, ZF, CF, and OF bits in the EFLAG register on x86. These bits are used to support conditional execution in conditionals and loops at the assembly level. We will cover condition codes used in Part 6: Conditional Execution and Branching

$cpsr寄存器显示出CPSR寄存器的当前值,在他的下面一行,你可以看到标志位 thumb, fast, interrupt, overflow, carry, zero, 以及 negative。这些标志位显示了CPSR寄存器中的某些特定的位,根据CPSR的值,当某个位被激活时,对应的字体会变成粗体。其中,N,Z,C和V标志位分别和x86寄存器的SF,ZF,CF和OF标志位表示的含义一一对应。这些标志位用来在汇编级别条件执行指令和循环指令中支配他们执行。我们会在第六节 条件执行及分支 中覆盖条件代码的知识 。




[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2018-8-7 17:59 被r0Cat编辑 ,原因:
收藏
免费 1
支持
分享
打赏 + 3.00雪花
打赏次数 2 雪花 + 3.00
 
赞赏  luoyesiqiu   +2.00 2018/08/06
赞赏  junkboy   +1.00 2018/06/07
最新回复 (19)
雪    币: 11716
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
支持                     
2018-6-7 16:06
0
雪    币: 7016
活跃值: (4227)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
不错,  很喜欢中英文对照的风格
2018-6-7 16:25
0
雪    币: 8715
活跃值: (8619)
能力值: ( LV13,RANK:570 )
在线值:
发帖
回帖
粉丝
4
junkboy 支持
感谢感谢
2018-6-7 16:41
0
雪    币: 8715
活跃值: (8619)
能力值: ( LV13,RANK:570 )
在线值:
发帖
回帖
粉丝
5
MaYil 不错, 很喜欢中英文对照的风格
继续发扬~
2018-6-7 16:41
0
雪    币: 59
活跃值: (680)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
赞一个
2018-6-9 13:44
0
雪    币: 3907
活跃值: (5817)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
7
不错
2018-6-10 18:33
0
雪    币: 4139
活跃值: (2854)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
8
这一系列文章我看过,很不错.加油
2018-6-10 19:03
0
雪    币: 17
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
666支持
2018-6-11 08:53
0
雪    币: 689
活跃值: (422)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
10
楼主,寄存器的图片是用什么画出来的还是原文附带的?
2018-6-11 15:27
0
雪    币: 8715
活跃值: (8619)
能力值: ( LV13,RANK:570 )
在线值:
发帖
回帖
粉丝
11
zplusplus 楼主,寄存器的图片是用什么画出来的还是原文附带的?
你好,有些是原文附带的,有些是截屏,是为了达到更好的视觉效果才分情况对待的。文末有原文链接,可以进去查看哦
最后于 2018-6-11 16:04 被r0Cat编辑 ,原因:
2018-6-11 16:03
0
雪    币: 689
活跃值: (422)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
12
amzilun zplusplus 楼主,寄存器的图片是用什么画出来的还是原文附带的? 你好,有些是原文附带的,有些是截屏,是为了达到更好的视觉效果才分情况对待的。文末 ...
好的,谢谢
2018-6-12 11:41
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
挺不错的  但是ARM指令集那么多  够讲好多课了
2018-6-13 16:31
0
雪    币: 2685
活跃值: (3710)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
14
不错,学习了
2018-8-6 17:28
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
赞一个
2018-8-7 10:06
0
雪    币: 129
活跃值: (407)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
文中有一处错误,请及时更正
“无符号类型可以包含正数(包括0),但是不能包含正数,因此他的取值范围更大”
应当是 “但是不能包含负数”
2018-8-7 10:51
0
雪    币: 8715
活跃值: (8619)
能力值: ( LV13,RANK:570 )
在线值:
发帖
回帖
粉丝
17
SevenSir 文中有一处错误,请及时更正 “无符号类型可以包含正数(包括0),但是不能包含正数,因此他的取值范围更大” 应当是 “但是不能包含负数”
收到,已改正,感谢提醒
2018-8-7 17:59
0
雪    币: 59
活跃值: (680)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
很多地方都错了。。
系统调用发生时,R11开始生效,它存储了系统调用数值 
--这里应该是R7
当加法,减法或者比较指令的结果大于或者等于231或是小于或者等于-231时会产生溢出
--这里应该是2^31
--同理上面应该是2^32


2018-12-3 16:25
0
雪    币: 120
活跃值: (1597)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
哇,中英文对照!
2019-4-16 10:41
0
雪    币: 758
活跃值: (78)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
学习了!
2019-11-14 09:59
0
游客
登录 | 注册 方可回帖
返回
//