使用链接描述文件中的位置计数器会影响哪些内存?

疯狂的编码器

我正在学习汇编的乐趣,而这只是我今天的第三天。也许我误解了链接描述文件中的位置计数器。根据我的理解,位置计数器定义了内存中的哪个地址,这些段必须加载到内存中(物理或虚拟)。

但是,从该SO帖子中获取的以下链接程序脚本似乎会更改生成的图像(将幻数放在生成的MBR图像的最后2个字节中)。

链接

SECTIONS
{
    /* The BIOS loads the code from the disk to this location.
     * We must tell that to the linker so that it can properly
     * calculate the addresses of symbols we might jump to.
     */
    . = 0x7c00;
    .text :
    {
        __start = .;
        *(.text)
        /* Place the magic boot bytes at the end of the first 512 sector. */
        . = 0x1FE;
        SHORT(0xAA55)
    }
}

我的代码是:

电源

.code16
    mov $msg, %si
    mov $0x0e, %ah
loop:
    lodsb
    or %al, %al
    jz halt
    int $0x10
    jmp loop
halt:
    hlt
msg:
    .asciz "hello world"

我组装并链接:

as -g -o main.o main.S
ld --oformat binary -o main.img -T link.ld main.o
qemu-system-x86_64 -hda main.img

很快我意识到该选项--oformat binary必须对此做一些事情,因为排除该选项不会创建512字节的图像。也许我应该在寻找ELF vs二进制格式?有人可以帮我理解为什么使用binary格式,如何解释位置计数器(因为它也应该做些什么. = 0x7C00)吗?

生成的512字节的hello世界映像的十六进制转储给我这个:

00000000  bf 0f 7c b4 0e ac 08 c0  74 04 cd 10 eb f7 f4 68  |..|.....t......h|
00000010  65 6c 6c 6f 20 77 6f 72  6c 64 00 66 2e 0f 1f 84  |ello world.f....|
00000020  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
00000030  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
00000040  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
00000050  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
00000060  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
00000070  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
00000080  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
00000090  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
000000a0  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
000000b0  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
000000c0  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
000000d0  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
000000e0  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
000000f0  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
00000100  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
00000110  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
00000120  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
00000130  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
00000140  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
00000150  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
00000160  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
00000170  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
00000180  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
00000190  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
000001a0  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
000001b0  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
000001c0  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
000001d0  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
000001e0  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
000001f0  00 66 2e 0f 1f 84 00 00  00 00 00 0f 1f 00 55 aa  |.f............U.|
00000200

我不明白. = 0x7C00这里的影响吗?该信息丢失了吗?(可能不需要,因为GRUB始终会在0x7C00加载它)

老旧的计时器
. = 0x7c00;
.text :
{
    __start = .;
    *(.text)
    /* Place the magic boot bytes at the end of the first 512 sector. */
    . = 0x1FE;
    SHORT(0xAA55)
}

0x7C00,您正在告诉链接程序(这不是BTW的汇编语言,不相关)。我希望接下来的事情是在地址空间(对于处理器)中的地址0x7C00处。下方带有.text,这表示我们希望从地址0x7C00开始链接.text代码。因此,如果有任何特定位置,则它将基于该地址。

__start给我到目前为止的地址(.text中)

*(。text)将所有.text代码放在此处

= 0x1FE将指针移动到.text中的0x1FE

SHORT(0xAA55)将这两个字节放在.text中的偏移量0x1Fe和0x1FF处

因此,假设代码适合,那么将产生一个0x200字节的Blob,该地址将在地址空间的0x7C00处加载。

现在,当您objcopy -O二进制hello.elf hello.bin

该工具将查找第一个可加载对象,而输出文件的第一部分就是该第一个可加载对象。如果这是“二进制”中仅有的内容,则0x200字节将进入文件hello.bin。

该-O二进制文件格式丢失了告诉处理器0x7C00所需信息的信息。精灵拥有它,其他拥有它,但是那个没有。

此外,如果在0x7C00具有0x200字节,在0x8000具有2个字节,那么-O二进制输出将为0x402字节长。前0x200字节来自最低可加载内容的0x7C00的.text,然后是0x200字节的填充字节,因此,相对于文件开头的第二个字节位于正确的位置(如果要使用hello.bin并放入在0x7c00,则这两个字节将在0x8000。

如果您在0x7C00处有这些0x200,并且要在链接脚本中添加另一个项目,并在0x7000处使用0x02字节,那么hello.bin将以这两个字节开头,将有0xBFE填充字节,然后是.text的0x200字节。因此,当将bin文件以0x7000加载到内存中时,两个字节和0x200字节位于正确的位置。

因此,objcopy -O binary本质上创建了一个需要加载的内存映像,有时使用填充,但是没有有关该加载的起始地址的信息。您必须知道。

elf文件也将以某种形式包含0xAA55,我认为整个0x200字节是.text中显示的一件事,但也许将其分为两部分。取决于创建小精灵的工具的填充方式和填充方式。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用 Python 递增存储在文件中的计数器

来自分类Dev

使用计数器获取文件夹中多个文件的文件第二行

来自分类Dev

有哪些数据计数器/仪表?

来自分类Dev

如何使用无序链接创建页面计数器

来自分类Dev

文件数计数器

来自分类Dev

Android-如何使用Java文件中的计数器查找资源/图像名称?

来自分类Dev

使用Python 3读取和递增文件中的计数器

来自分类Dev

文本文件中的元音计数器

来自分类Dev

在Angular中的html文件上添加计数器

来自分类Dev

文本文件中的元音计数器

来自分类Dev

如何使用性能计数器控制从文件读取?

来自分类Dev

BASH文件使用计数器批量重命名

来自分类Dev

Python中的计数器

来自分类Dev

使用CSS计数器

来自分类Dev

链接描述文件::动态内存部分

来自分类Dev

自定义计数器文件视图的内存不足

来自分类Dev

如何使用##在C中粘贴术语和计数器?

来自分类Dev

如何使用python在计数器中应用嵌套条件?

来自分类Dev

使用GetElementsByClass在计数器中添加双重“ if”功能

来自分类Dev

使用addEventListener来更新/增加Javascript中的计数器

来自分类Dev

使用游标在SQL中创建计数器

来自分类Dev

FPGA重置中的计数器错误(使用VHDL)

来自分类Dev

如何使用##在C中粘贴术语和计数器?

来自分类Dev

哪些因素会影响Google Chrome浏览器中的用户指标风格?

来自分类Dev

嵌入式 C 中的 FIFO 队列 - 计数器会溢出吗?

来自分类Dev

用循环计数器命名文件

来自分类Dev

计数器读写txt文件-vbscript

来自分类Dev

用循环计数器命名文件

来自分类Dev

CSV文件的Python计数器