Gcc 链接器脚本-位置计数器和丢弃节
我正在关注hello world引导扇区程序,该程序具有以下链接器脚本: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
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