Assembly 什么是可重定位和绝对机器代码?
在研究汇编程序时,我遇到了这些术语。我的想法是,在可重定位机器代码中,代码不依赖于静态RAM位置。汇编程序为我的程序指定RAM需求。内存可以放在链接器为它们找到空间的任何地方 这个想法正确吗?如果是,汇编程序是如何完成的Assembly 什么是可重定位和绝对机器代码?,assembly,relocation,Assembly,Relocation,在研究汇编程序时,我遇到了这些术语。我的想法是,在可重定位机器代码中,代码不依赖于静态RAM位置。汇编程序为我的程序指定RAM需求。内存可以放在链接器为它们找到空间的任何地方 这个想法正确吗?如果是,汇编程序是如何完成的 还有,什么是绝对机器代码的例子?任何在代码中实际包含地址的东西都有绝对地址。代码中不包含地址的程序(所有操作都使用相对地址完成)可以从任何地址运行 汇编程序不这样做,程序员这样做。我在过去做过一些,对于小的东西通常很容易,一旦你超出了相对跳跃的范围,就会变得相当痛苦。IIRC唯
还有,什么是绝对机器代码的例子?任何在代码中实际包含地址的东西都有绝对地址。代码中不包含地址的程序(所有操作都使用相对地址完成)可以从任何地址运行 汇编程序不这样做,程序员这样做。我在过去做过一些,对于小的东西通常很容易,一旦你超出了相对跳跃的范围,就会变得相当痛苦。IIRC唯一的两种方法是在例程之间滑动相对跳转,或者向当前地址添加一个已知偏移量,按下它,然后返回。在过去,有第三种方法可以计算它并将其写入代码中,但这已不再被接受。这已经足够长了,我不会发誓没有其他的方法 IIRC“调用”没有绝对地址的东西的唯一方法是推送你想要返回的地址,计算地址,推送并返回
请注意,在实践中,您通常使用混合方法。汇编程序和链接器存储进行调整所需的信息,当程序加载到内存中时,它被修改为在加载时的任何地址运行。因此,内存中的实际图像是绝对的,但磁盘上的文件工作起来就像是相对的,但没有通常带来的所有麻烦。(请注意,所有实际生成本机代码的高级语言都使用相同的方法。)许多/大多数指令集具有pc相对寻址,这意味着采用与正在执行的指令地址相关的程序计数器地址,然后在上面加一个偏移量,用它来访问内存或分支之类的东西。这就是你所说的可重新定位。因为不管指令在地址空间中的什么位置,你想要跳转到的东西都是相对的。将整个代码块和数据移动到其他地址,它们之间的距离仍然相对相同,因此相对寻址仍然有效。如果相等,则跳过下一条指令,无论这三条指令位于何处(如果跳过、跳过的指令和跳过后的指令) 绝对使用绝对地址,跳转到此确切地址,从该确切地址读取。如果相等,则分支到0x1000 汇编程序不会这样做,编译器和/或程序员会这样做。通常,编译后的代码最终将具有绝对寻址,特别是当您的代码由链接在一起的独立对象组成时。在编译时,编译器无法知道对象将在哪里结束,也无法知道外部引用的位置或距离,因此通常无法假定它们足够接近pc相对寻址(通常有范围限制)。因此,编译器通常会为链接器生成一个占位符,用绝对地址填充。至于如何解决这个外部地址问题,它确实取决于操作和指令集以及其他一些因素。最终,尽管基于项目大小,链接器最终还是会得到一些绝对地址。因此,非默认值通常是一个命令行选项,用于生成与位置无关的代码——例如,PIC可能是编译器支持的。然后,编译器和链接器都必须做额外的工作,以使这些项位置独立。汇编语言程序员必须自己完成这项工作,汇编程序通常不参与其中,它只是为您告诉它生成的指令创建机器代码 Novectos.s:
.globl _start
_start:
b reset
reset:
mov sp,#0xD8000000
bl notmain
ldr r0,=notmain
blx r0
hang: b hang
.globl dummy
dummy:
bx lr
你好,c
extern void dummy ( unsigned int );
int notmain ( void )
{
unsigned int ra;
for(ra=0;ra<1000;ra++) dummy(ra);
return(0);
}
hello_world.list(我们关心的部件)
0xD600001c是该位置
d600000c: e59f0008 ldr r0, [pc, #8] ; d600001c <dummy+0x4>
d6000010: e12fff30 blx r0
...
d600001c: d6000020 strle r0, [r0], -r0, lsr #32
是pc相对寻址吗?我刚才说的这个指令集的工作方式是在执行时,pc在前面两条指令,或者基本上在这种情况下,如果指令在内存中是0xD60000C,那么pc在执行时将是0xD6000014,然后在指令状态下加上8,得到0xD600001C。但如果我们将完全相同的机器代码指令移动到地址0x1000,并将所有周围的二进制文件(包括它正在读取的内容)(0xD6000020)移动到地址0x1000。基本上是这样做的:
1000: e59f0008 ldr r0, [pc, #8]
1004: e12fff30 blx r0
...
1010: d6000020
这些指令,机器代码仍然有效,不需要重新组装或链接。0xD6000020代码必须位于ldr pc和blx不允许的固定地址位
虽然反汇编程序显示这些带有0xd6。。。基于地址的bl和bne也是与pc相关的,您可以通过查看指令集文档来了解它们
d6000030: ebfffff8 bl d6000018 <dummy>
d6000034: e3540ffa cmp r4, #1000 ; 0x3e8
d6000038: 1afffffa bne d6000028 <notmain+0x8>
看看有什么机器代码改变了,有什么没有改变
00001000 <_start>:
1000: eaffffff b 1004 <reset>
00001004 <reset>:
1004: e3a0d336 mov sp, #-671088640 ; 0xd8000000
1008: eb000004 bl 1020 <notmain>
100c: e59f0008 ldr r0, [pc, #8] ; 101c <dummy+0x4>
1010: e12fff30 blx r0
00001014 <hang>:
1014: eafffffe b 1014 <hang>
00001018 <dummy>:
1018: e12fff1e bx lr
101c: 00001020 andeq r1, r0, r0, lsr #32
00001020 <notmain>:
1020: e92d4010 push {r4, lr}
1024: e3a04000 mov r4, #0
1028: e1a00004 mov r0, r4
102c: e2844001 add r4, r4, #1
1030: ebfffff8 bl 1018 <dummy>
1034: e3540ffa cmp r4, #1000 ; 0x3e8
1038: 1afffffa bne 1028 <notmain+0x8>
103c: e3a00000 mov r0, #0
1040: e8bd4010 pop {r4, lr}
1044: e12fff1e bx lr
000011000:
1000:eaffffff b 1004
00001004 :
1004:e3a0d336 mov sp,#-671088640;0xd8000000
1008:eb000004 bl 1020
100c:e59f0008 ldr r0,[pc,#8];101c
1010:E12FF30 blx r0
00001014 :
1014:eafffffe b 1014
00001018 :
1018:E12FF1E bx lr
101c:00001020安第克r1、r0、r0、lsr#32
00001020 :
1020:e92d4010推送{r4,lr}
1024:e3a04000 mov r4,#0
1028:e1a00004 mov r0,r4
102c:e2844001添加r4、r4和#1
1030:ebfffff8 bl 1018
1034:e3540ffa cmp r4,#1000;0x3e8
1038:1AFFFA bne 1028
103c:e3a00000 mov r0,#0
1040:e8bd4010 pop{r4,lr}
1044:E12FF1E bx lr
基本上,“绝对”模式意味着代码和RAM变量将精确地放置在
ldr r0, [pc, #8]
1000: e59f0008 ldr r0, [pc, #8]
1004: e12fff30 blx r0
...
1010: d6000020
d6000030: ebfffff8 bl d6000018 <dummy>
d6000034: e3540ffa cmp r4, #1000 ; 0x3e8
d6000038: 1afffffa bne d6000028 <notmain+0x8>
d600000c: e59f0008 ldr r0, [pc, #8] ; d600001c <dummy+0x4>
d6000010: e12fff30 blx r0
MEMORY
{
ram : ORIGIN = 0x1000, LENGTH = 0x4000
}
SECTIONS
{
.text : { *(.text*) } > ram
}
00001000 <_start>:
1000: eaffffff b 1004 <reset>
00001004 <reset>:
1004: e3a0d336 mov sp, #-671088640 ; 0xd8000000
1008: eb000004 bl 1020 <notmain>
100c: e59f0008 ldr r0, [pc, #8] ; 101c <dummy+0x4>
1010: e12fff30 blx r0
00001014 <hang>:
1014: eafffffe b 1014 <hang>
00001018 <dummy>:
1018: e12fff1e bx lr
101c: 00001020 andeq r1, r0, r0, lsr #32
00001020 <notmain>:
1020: e92d4010 push {r4, lr}
1024: e3a04000 mov r4, #0
1028: e1a00004 mov r0, r4
102c: e2844001 add r4, r4, #1
1030: ebfffff8 bl 1018 <dummy>
1034: e3540ffa cmp r4, #1000 ; 0x3e8
1038: 1afffffa bne 1028 <notmain+0x8>
103c: e3a00000 mov r0, #0
1040: e8bd4010 pop {r4, lr}
1044: e12fff1e bx lr