jyy操作系统课中《为 Bare-Metal 编程:编译、链接与加载》的一些问题的解决

直接说重点:

在文档中的

3. Bare-Metal 上的 C 程序

其中的

3.1. 链接

有以下命令

$ ld -melf_x86_64 -N -Ttext-segment=0x00100000 -o build/hello-x86_64-qemu.o \
  main.o say.o am-x86_64-qemu.a klib-x86_64-qemu.a

 容易发现这个 am-x86_64-qemu.a和 klib-x86_64-qemu.a是哪里来的?

查看abstract-machine的根目录的Makefile其中有

ARCHIVE   = $(WORK_DIR)/build/$(NAME)-$(ARCH).a

 可以知道肯定是和这个文件有关,这个命令就是.a文件的来源尝试使用命令

root@87f95c70b3ff:/home/newos/os-workbench/abstract-machine# make AM_HOME=. ARCH=x86_64-qemu

Makefile:40: *** Nothing to build.  Stop.

 说明有问题,查看了所有的makefile之后发现只要进入到子文件中就可以

 root@87f95c70b3ff:/home/newos/os-workbench/abstract-machine/am# make AM_HOME=./.. ARCH=x86_64-qemu        
# Building am-image [x86_64-qemu]
+ AS src/x86/qemu/start64.S
+ AS src/x86/qemu/trap64.S
+ CC src/x86/qemu/trm.c
+ CC src/x86/qemu/cte.c
+ CC src/x86/qemu/ioe.c
+ CC src/x86/qemu/vme.c
+ CC src/x86/qemu/mpe.c
# Building am-archive [x86_64-qemu]
+ AR -> build/am-x86_64-qemu.a
# Building klib-archive [x86_64-qemu]
+ CC src/stdio.c
+ CC src/stdlib.c
+ CC src/string.c
+ CC src/cpp.c
+ CC src/int64.c
+ AR -> build/klib-x86_64-qemu.a
+ LD -> build/am-x86_64-qemu.elf
x86_64-linux-gnu-ld: /home/newos/os-workbench/abstract-machine/am/build/x86_64-qemu/src/x86/qemu/trm.o: in function `call_main':
trm.c:(.text+0xbb): undefined reference to `main'
make: *** [../Makefile:131: /home/newos/os-workbench/abstract-machine/am/build/am-x86_64-qemu.elf] Error 1

然后在当前目录下的bulid下就可以找到对应的.a文件 

如果直接使用文档中的命令链接这两个文件还是会有问题

ld -melf_x86_64 -N -Ttext-segment=0x00100000 -o build/hello-x86_64-qemu.o \
  main.o say.o am-x86_64-qemu.a klib-x86_64-qemu.a
ld: say.o: in function `say':
say.c:(.text+0x11): undefined reference to `putchar'

 putchar这个应该是C语言中的一个功能,打算在没有环境的am上运行显然是不可能的,检查代码,发现

// say.c
void putch(char ch);
int putchar(int ch);

void say(const char *s) {
  for (; *s; s++) {
#ifdef __ARCH__
    putch(*s); // AbstractMachine,没有 libc,调用 TRM API 打印字符
#else
    putchar(*s); // 操作系统,调用 libc 打印字符
#endif
  }
}

也就是说,我们之前的编译没有__ARCH__这个宏,所以需要重新编译say.o

root@87f95c70b3ff:/home/os-workbench/abstract-machine/src# rm say.o
root@87f95c70b3ff:/home/os-workbench/abstract-machine/src# gcc -c -D__ARCH__ -O2 -o say.o say.c
 

这样出来的say.o就符合我们的需求了,

再次进行编译

root@87f95c70b3ff:/home/os-workbench/abstract-machine/src# ld -melf_x86_64 -N -Ttext-segment=0x00100000 -o build/hello-x86_64-qemu.o   main.o say.o am-x86_64-qemu.a klib-x86_64-qemu.a
 

通过

但是这个还是没有完成整个实验,后续的命令中

( cat abstract-machine/am/src/x86/qemu/boot/mbr \
  head -c 1024 /dev/zero \
  cat build/hello-x86_64-qemu.o ) \
  > /tmp/hello/build/hello-x86_64-qemu

 其实是找不到mbr的文件的,暂时还没有方法解决,也希望有解决的小伙伴帮忙一下

当天更新:

找到mbr了,先看了一下boot目录里面的文件觉得有可能是mbr,但是输出是bootloader.o有点不明所以,但是其中有一个py文件,查看内容如下:

import os, sys, pathlib, subprocess

f = pathlib.Path(sys.argv[1])

try:

    objcopy = os.getenv('CROSS_COMPILE', '') + 'objcopy'

    data = subprocess.run(

        [objcopy, '-S', '-O', 'binary', '-j', '.text', f, '/dev/stdout'],

        capture_output=True).stdout

    assert len(data) <= 510

    data += b'\0' * (510 - len(data)) + b'\x55\xaa'

    f.write_bytes(data)

except:

    f.unlink()

    raise

 可以看到里面有一个是往里面添加了一个x55xaa,这个不就是mbr的结尾吗,所以我更加坚定了bootloader.o就是我要的mbr的想法,直接mv重命名为mbr,但是后面还有坑,我在执行

( cat abstract-machine/am/src/x86/qemu/boot/mbr \
  head -c 1024 /dev/zero \
  cat build/hello-x86_64-qemu.o ) \
  > /tmp/hello/build/hello-x86_64-qemu

的时候,会报错cat没有c这个参数,试了各种办法都还是这样,我只能把它拆成三个部分运行

 root@87f95c70b3ff:/home/os-workbench/abstract-machine# cat am/src/x86/qemu/boot/mbr >> hello-x86_64-qemu
root@87f95c70b3ff:/home/os-workbench/abstract-machine# head -c 1024 /dev/zero >> hello-x86_64-qemu 
root@87f95c70b3ff:/home/os-workbench/abstract-machine# cat build/hello-x86_64-qemu.o >> hello-x86_64-qemu 

应该没有什么区别把,总之我的结果是出来了 

 root@87f95c70b3ff:/home/os-workbench/abstract-machine# file hello-x86_64-qemu 
hello-x86_64-qemu: DOS/MBR boot sector; partition 1 : ID=0x29, active 0xe4, start-CHS (0x38,141,20), end-CHS (0xc0,249,49), startsector 2868107145, 3296970219 sectors

 后面的结果也都差不多,真不容易啊,但是靠自己解决问题还是挺有成就感的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值