记录x86汇编的学习

瞎写

现在都快两点了,不怎么困…

今天也是摸鱼的一天…

其实还是有些收获的,至少怎么写链接脚本,怎么写MBR扇区的代码,还算是了解了一点点。(并没有学习x86汇编)

总结一下吧。


总结

东西很杂,就随便记录一下

i386 裸机环境搭建

1. 编译 binutils

2. 编译 gcc

binutils 和 gcc 的源码可以去清华[1]或者科大的镜像站上面找,编译主要就是下面这几句:

1
2
3
4
5
6
7
8
9
10
11
# Varibale Settings
export PREFIX=/usr/local/install_path
export TARGET=i686-elf
export PATH="${PREIFX}/bin:${PATH}"

# binutils configure
binutils-xxx/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-werror

# gcc configure
gcc-xxx/configure --target=$TARGET --prefix="$PREFIX" --enable-languages=c,c++ --without-headers

上面的内容是经过简化的,没把

make
sudo make install

写在里面,配置选项也很简单。

具体内容可以在 OSDev Wiki [2]上面找到,我就不写(抄)了。

关于x86汇编的“方言”

其实是两种语法(syntax):

AT&A 和 Intel

我是最近刚看的《汇编语言》第三版,上面讲的是 Intel 语法,而我打算用GAS来做汇编器,GAS默认使用 AT&T 语法,这让我刚开始很困扰。不过后来我发现可以用一些编译指令[3]来使用 Intel 语法。这也不算个问题了。

关于链接脚本

如何把MagicNumber放到最后面就是用的链接脚本。链接脚本指导连接器如何从对象文件里面获取所需要的内容,如何将这些内容在输出的文件中进行布局。具体参考官方手册[4]。

MBR引导代码

大概半年前我才装上Ununtu真机。以前都是用虚拟机。装的时候搞出了点事情,发现我自己用的不是UEFI启动。用的还是Legacy BIOS。然后我就重新建立ESP分区,把Win10和Ubuntu的引导扔进去,加上GRUB。其实这里面的东西也能写一篇博客,因为遇到的问题还是挺多的。

MBR 是给 Legacy BIOS用的。存储设备的第一个扇区(Sector)的最后两个字节是0x550xaa,就会被BIOS当成一个可以启动的设备,BIOS将其512KiB加载到 0x0000:0x7c00 然后从这里开始运行。所以关键就是用链接脚本把 magic number 放到最后面,.text 放到最前面就好了。

给一个简单的小例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SECTIONS
{
/* BIOS will jump to here to run */
. = 0x00;


.text :
{

*(.text)

}

allsize = ABSOLUTE(.);
.mbrcheck :
{

. = 512K - allsize - 2;
boot.o(.mbrcheck)

}
}

链接的结果是生成ELF文件,用objcopy把没用的ELF头和符号表给去掉,生成Binary文件。这时候就可以尝试用Qemu来模拟了。


Reference

  1. 清华大学开源软件镜像站, “Index of /gnu/“, https://mirrors.tuna.tsinghua.edu.cn/gnu/
  2. OSDev-Wiki, “GCC Cross-Compiler”, https://wiki.osdev.org/GCC_Cross-Compiler
  3. Stackoverflow, “Can I use Intel syntax of x86 assembly with GCC?”, https://stackoverflow.com/questions/9347909/can-i-use-intel-syntax-of-x86-assembly-with-gcc
  4. Sourceware, “ld-docs”, https://sourceware.org/binutils/docs/ld/index.html