Gcc 链接器脚本-位置计数器和丢弃节

Gcc 链接器脚本-位置计数器和丢弃节,gcc,assembly,ld,x86-16,linker-scripts,Gcc,Assembly,Ld,X86 16,Linker Scripts,我正在关注hello world引导扇区程序,该程序具有以下链接器脚本: ENTRY(mystart) SECTIONS { . = 0x7c00; .text : { entry.o(.text) *(.text) *(.data) *(.rodata) __bss_start = .; *(.bss) *(COMMON) __bss_end = .; } .sig : AT(ADDR(.text) + 512

我正在关注hello world引导扇区程序,该程序具有以下链接器脚本:

ENTRY(mystart)
SECTIONS
{
  . = 0x7c00;
  .text : {
    entry.o(.text)
    *(.text)
    *(.data)
    *(.rodata)
    __bss_start = .;
    *(.bss)
    *(COMMON)
    __bss_end = .;
  }

  .sig : AT(ADDR(.text) + 512 - 2)
  {
      SHORT(0xaa55);
  }
  /DISCARD/ : {
    *(.eh_frame)
  }
  __stack_bottom = .;
  . = . + 0x1000;
  __stack_top = .;
}
以下是
条目.S

.code16
.text
.global mystart
mystart:
    ljmp $0, $.setcs
.setcs:
    xor %ax, %ax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %ss
    mov $__stack_top, %esp
    cld
    call main
以下是
主功能

void main(void) {
    int i;
    char s[] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};
    for (i = 0; i < sizeof(s); ++i) {
        __asm__ (
            "int $0x10" : : "a" ((0x0e << 8) | s[i])
        );
    }
    while (1) {
        __asm__ ("hlt");
    };
}
将0x8c93推入%esp


为什么会这样?
eh_frame
是否有任何影响,或者我是否遗漏了什么?请帮忙。

这是一个猜测,我没有时间加载这个来尝试。处理
.text
部分后,VMA(虚拟内存地址)为0x7c91。当您发出.sig`节,但只告诉该节修改LMA(加载内存地址)并将其指向0x7e00-2时。完成
.sig
部分后,VMA增加2(您发出了2个字节0xaa55)到0x7c93,LMA现在为0x7e00。当您执行
=.+0x1000
您正在将0x1000添加到当前的VMA,即0x7c93。0x7c93+0x1000=0x8C93要解决此问题,您可以在输出
.sig
部分时设置VMA和LMA。这是否有效:
.sig 0x7dfe:AT(ADDR(.text)+512-2)
。或者,您可以将
=0x7e00就在
堆栈底部=
所以VMA被提升到0x7e00。@MichaelPetch:在阅读您的评论后,我验证了.text部分确实以0x7c93结尾。而且,这两种解决方案都有效。我现在也明白了整个问题的存在,因为.文本大小小于510字节。因此,尽管LMA和VMA在.text节开始时是相同的,但在.sig节期间,由于大小的差异,它们变得不同。然而,我并不完全清楚VMA和LMA。LMA是指磁盘映像地址,VMA是指RAM中运行时的地址吗?请您澄清一下VMA和DMA。VMA是运行输出文件时该部分的地址。LMA是将加载节的地址。GNU LD页面上有文档和示例:。这里描述了VMA和LMA:“0x1000(16 MB堆栈)”--这不可能,因为16 MiB在Real 86模式下不可寻址。向偏移量添加1000小时会使偏移量提前4千磅,因此,如果将sp设置为8E00h,则会有一个4千磅的堆栈。这是一个猜测,我没有时间加载该堆栈进行尝试。处理
.text
部分后,VMA(虚拟内存地址)为0x7c91。当您发出.sig`节,但只告诉该节修改LMA(加载内存地址)并将其指向0x7e00-2时。完成
.sig
部分后,VMA增加2(您发出了2个字节0xaa55)到0x7c93,LMA现在为0x7e00。当您执行
=.+0x1000
您正在将0x1000添加到当前的VMA,即0x7c93。0x7c93+0x1000=0x8C93要解决此问题,您可以在输出
.sig
部分时设置VMA和LMA。这是否有效:
.sig 0x7dfe:AT(ADDR(.text)+512-2)
。或者,您可以将
=0x7e00就在
堆栈底部=
所以VMA被提升到0x7e00。@MichaelPetch:在阅读您的评论后,我验证了.text部分确实以0x7c93结尾。而且,这两种解决方案都有效。我现在也明白了整个问题的存在,因为.文本大小小于510字节。因此,尽管LMA和VMA在.text节开始时是相同的,但在.sig节期间,由于大小的差异,它们变得不同。然而,我并不完全清楚VMA和LMA。LMA是指磁盘映像地址,VMA是指RAM中运行时的地址吗?请您澄清一下VMA和DMA。VMA是运行输出文件时该部分的地址。LMA是将加载节的地址。GNU LD页面上有文档和示例:。这里描述了VMA和LMA:“0x1000(16 MB堆栈)”--这不可能,因为16 MiB在Real 86模式下不可寻址。向偏移量添加1000小时会使偏移量提前4千磅,因此,如果将sp设置为8E00h,则会有一个4千磅的堆栈。
mov $__stack_top, %esp