- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在学习汇编程序时,我遇到了这些术语。我的想法是这样的,在可重定位的机器代码中,代码不依赖于静态RAM位置。汇编程序为我的程序指定RAM需求。可以在链接器为它们找到空间的任何地方放置内存。
这个想法正确吗?如果是这样,汇编程序如何完成?
而且,绝对机器代码有哪些示例?
最佳答案
许多/大多数指令集具有pc相对地址,这意味着获取程序计数器的地址(与您正在执行的指令的地址相关),然后为其添加一个偏移量,并将其用于访问内存或分支等。那。那就是您所说的可重定位的东西。因为无论该指令在地址空间中的哪个位置,您都想跳转到的都是相对的。将整个代码和数据块移至其他地址,它们之间的距离仍然相对相同,因此相对寻址仍然有效。如果相等,则下一条指令将在这三条指令所在的位置(如果已跳过,则一条将被跳过,然后是一条跳过)将起作用。
绝对使用绝对地址,跳转到该确切地址,然后从该确切地址读取。如果相等,则跳转到0x1000。
汇编器不会这样做,编译器和/或程序员会这样做。通常,最终,编译后的代码最终将具有绝对寻址,尤其是如果您的代码由链接在一起的单独对象组成时。在编译时,编译器无法知道对象将在哪里结束,也无法知道外部引用在哪里或距离多远,因此通常不能假定它们将足够接近以进行pc相对寻址(通常具有范围限制) 。因此,编译器通常会为链接器生成一个占位符,以填充一个绝对地址。它确实取决于操作和指令集以及其他有关如何解决此外部地址问题的因素。最终,尽管基于项目大小,链接器最终仍会进行一些绝对寻址。因此,非默认值通常是用于生成位置无关代码的命令行选项-例如,PIC可能是编译器支持的内容。然后,编译器和链接器都必须做额外的工作以使这些项目位置独立。汇编语言程序员必须自己完成所有工作,汇编程序通常不会参与其中,它只是为您告诉它生成的指令创建机器代码。
novectors.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
extern void dummy ( unsigned int );
int notmain ( void )
{
unsigned int ra;
for(ra=0;ra<1000;ra++) dummy(ra);
return(0);
}
ARMGNU = arm-none-eabi
COPS = -Wall -O2 -nostdlib -nostartfiles -ffreestanding
all : hello_world.bin
clean :
rm -f *.o
rm -f *.bin
rm -f *.elf
rm -f *.list
novectors.o : novectors.s
$(ARMGNU)-as novectors.s -o novectors.o
hello.o : hello.c
$(ARMGNU)-gcc $(COPS) -c hello.c -o hello.o
hello_world.bin : memmap novectors.o hello.o
$(ARMGNU)-ld novectors.o hello.o -T memmap -o hello_world.elf
$(ARMGNU)-objdump -D hello_world.elf > hello_world.list
$(ARMGNU)-objcopy hello_world.elf -O binary hello_world.bin
Disassembly of section .text:
d6000000 <_start>:
d6000000: eaffffff b d6000004 <reset>
d6000004 <reset>:
d6000004: e3a0d336 mov sp, #-671088640 ; 0xd8000000
d6000008: eb000004 bl d6000020 <notmain>
d600000c: e59f0008 ldr r0, [pc, #8] ; d600001c <dummy+0x4>
d6000010: e12fff30 blx r0
d6000014 <hang>:
d6000014: eafffffe b d6000014 <hang>
d6000018 <dummy>:
d6000018: e12fff1e bx lr
d600001c: d6000020 strle r0, [r0], -r0, lsr #32
d6000020 <notmain>:
d6000020: e92d4010 push {r4, lr}
d6000024: e3a04000 mov r4, #0
d6000028: e1a00004 mov r0, r4
d600002c: e2844001 add r4, r4, #1
d6000030: ebfffff8 bl d6000018 <dummy>
d6000034: e3540ffa cmp r4, #1000 ; 0x3e8
d6000038: 1afffffa bne d6000028 <notmain+0x8>
d600003c: e3a00000 mov r0, #0
d6000040: e8bd4010 pop {r4, lr}
d6000044: e12fff1e bx lr
ldr r0,=notmain
blx r0
d600000c: e59f0008 ldr r0, [pc, #8] ; d600001c <dummy+0x4>
d6000010: e12fff30 blx r0
...
d600001c: d6000020 strle r0, [r0], -r0, lsr #32
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
关于assembly - 什么是可重定位和绝对机器代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22889719/
我被告知“汇编”是您在文件中编写的内容,让您的“汇编程序”将其转换为二进制代码。 但我看到这两个术语在各种作品中混合搭配。我什至听说你编写了“汇编器”,然后“汇编器”使其可执行。 正确的用词是什么?
我在正确终止用 Assembly 编写的 16 位 DOS 程序时遇到问题。这是部分代码: .386P .model flat stack_s segment stack 'stack'
我需要多少档才能正确执行以下指令。我对我所做的事情有些困惑,所以我在这里看到专家的答案。 lw $1,0($2); beq $1,$2,Label; 请注意,检查是否会发生分支将在解码阶段完成。但是在
我正在尝试在汇编中进行简单的乘法运算,但是由于某些原因,当标记了MUL函数时,我看不到寄存器会发生变化。 mov bx, 5 mov cx, 10 mul cx 最佳答案 这些称为指令,它们指定
我正在尝试在 Assembly 中实现递归斐波那契程序。但是,我的程序崩溃了,出现了未处理的异常,我似乎无法找出问题所在。我不怀疑这涉及我对堆栈的不当使用,但我似乎无法指出哪里...... .386
我编写了以下代码: .386 .model small .stack 100h .data text db "Paper",0 .code start : lea dx ,
我有一个用汇编语言编写的裸机 ARM 的启动代码,我正在尝试了解它是如何工作的。该二进制文件被写入一些外部闪存中,并在启动时将其自身的一部分复制到 RAM 中。尽管我读过这篇文章wikipedia e
我在数据部分定义了一个二维数组和两个一维数组(一个用于列总和,一个用于行总和),并且我编写了一个函数,将二维数组求和到一维数组中。我使用 eax 和 ebx 作为二维数组的索引,但是当 eax 或 e
我正在开始组装,我正在使用 nasm 来组装代码,我正在尝试处理驻留在内存中的字符串并更改它,我想检查一个字节是否在某个范围内(ascii),这样我就可以决定如何处理它,我似乎不知道如何检查一个值是否
虽然您通常不希望将一个整体程序集用于小型项目以外的任何事情,但可能会将事物分离得太多。 组装分离过多的迹象/气味是什么? 最佳答案 第一个(明显的)是:在一个有很多项目的解决方案中,其中只有少数(比如
我正在尝试编写斐波那契的汇编代码版本,它给出第 n 个斐波那契数并返回它。 出于某种原因,它在存储斐波那契数的返回值和添加它们时遇到问题。 我希望它打印第 n 个斐波那契数。 我对我的代码做了一些修改
我有一个最小的、可重现的示例有两个问题,该示例具有三个针对 .NET Core 3.1 的项目。但我也想以 .NET Standard 2.0 为目标。 该示例适用于需要在运行时加载程序集并使用提供的
: 运算符在汇编中做什么?代码如下:DS:DX我还没有找到该运算符(operator)的任何文档。(我正在使用 NASM) 最佳答案 那实际上只是一个寄存器分隔符,而不是运算符。这意味着使用 DX 寄
我在哪里可以找到为 gmp-5.0.0 编写的程序的汇编代码我正在使用 UBUNTU 和 G++ 编译器..编译代码的命令是“g++ test.cc -o outp -lgmp” 实际上我想知道在 1
我是组装新手,我有一个关于如何表示负数的问题 我有三个 DWORDS 变量,比如说: result DWORD 0 i DWORD 3 j DWORD 5 我想计算这个公式:result = i -
我想编写我的第一个汇编程序。我在论文上做了一些程序,但这是我第一次使用编译器。我正在使用 ideone .我的程序很简单, 翻译 A = 5 - A到 assembly NEG A ADD A, 5
程序集,masm 嘿,我写了宏来打印存储在 dane1 段中的 1 字节值。 我将值除以 16,然后将提醒推送到堆栈,直到值==0。然后我弹出提醒将它们转换为 ASCII 码,并打印它们。 有人可以看
我正在研究 nasm 的一个大学项目。唯一的问题是我无法生成 162 和 278 之间的偶数随机数。我尝试了很多算法,但似乎无法限制范围内的数字。 是否有一个小技巧或调整来获得所需的范围内的数字?目的
终于在无数次错误的漫长 session 之后,希望这是最后一个。 没有编译或运行时错误,只是一个逻辑错误。 编辑:(固定伪代码) 我的伪代码: first = 1; second = 1; thir
我知道在程序集r0中调用函数时,包含第一个参数,直到r3是第四个。我知道,当它超过四个时,将使用堆栈指针,但是我不太确定具体细节。 r0-r3仍然保持前四个,其余的进入堆栈吗?我正在看下面的程序集,试
我是一名优秀的程序员,十分优秀!