Orange'S 第一章实验

本实验在Linux环境上用gnu as汇编格式完成

    .code16
    .org 0x7c00
    movw %cs, %ax
    movw %ax, %ds
    movw %ax, %es
    movw $hello, %ax
    movw %ax, %bp
    movw $13, %cx
    movw $0x1301, %ax
    movw $0x000c, %bx
    xorb %dl, %dl
    int $0x10
    jmp .

hello:
    .asciz "hello, world\n"

    .org 0x7c00+510
    .byte 0x55, 0xaa

汇编:

$ as boot.s -o boot.o

这时候生成的boot.o是elf格式,而我们需要的是纯二进制格式
我们可以用objcopy命令把elf格式拷贝成二进制格式,命令如下:

$ objcopy -O binary boot.o boot.bin

然后我们用xxd命令观察一下boot.bin的内容

$ xxd -a boot.bin

00000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
00007c00: 8cc8 8ed8 8ec0 b81a 7c89 c5b9 0d00 b801  ........|.......
00007c10: 13bb 0c00 30d2 cd10 ebfe 6865 6c6c 6f2c  ....0.....hello,
00007c20: 2077 6f72 6c64 0a00 0000 0000 0000 0000   world..........
00007c30: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
00007df0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

发现在0x7c00之前全是0,我们要把它截断,使用命令如下:

$ xxd -p -s 0x7c00 boot.bin > boot.hex
$ xxd -p -r boot.hex > boot.bin

第一条命令是从偏移0x7c00处把boot.bin dump到boot.hex文件中
第二条命令是逆向操作,把boot.hex还原为二进制格式

上述转换也可以使用dd命令,如下:

dd if=boot.bin of=boot.out ibs=1 skip=31744 count=512
mv boot.out boot.bin

ibs表示input block size,这里设置为1个字节
skip表示跳过多少个ibs,这里是跳过31744即0x7c00个字节
count表示拷贝多少个ibs,这是是512个字节

我们再用xxd命令看一下boot.bin的内容

$ xxd -a boot.bin

00000000: 8cc8 8ed8 8ec0 b81a 7c89 c5b9 0d00 b801  ........|.......
00000010: 13bb 0c00 30d2 cd10 ebfe 6865 6c6c 6f2c  ....0.....hello,
00000020: 2077 6f72 6c64 0a00 0000 0000 0000 0000   world..........
00000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

ok,这下没问题了。
剩下的操作可以参照《Orange’S》上的步骤完成

bochsrc配置文件可以从bochs源代码目录下拷贝一份出来修改,源代码根目录下有一个.bochsrc文件,用ls -A命令才能显示出来。
其中有几处需要注释掉的,我是根据bochs报错信息,搜索关键字,然后注释掉。
效果如下图:
这里写图片描述

本来想在macOS上做实验的,结果发现macOS上的汇编器as
输出代码的时候 movw $hello, %ax 这条指令生成的机器码为 b8 00 00 其中hello的地址为0,macOS的汇编器把符号重定位的工作留给了ld。
在linux上的as生成的机器码为 b8 1a 7c,hello的地址为0x7c1a,这是对的。
当然在macOS上我们也可以通过编辑二进制文件来打个补丁。

如果借助连接器ld,就不用上面那么麻烦。
使用ld的话,汇编代码要略作修改,boot.s代码如下

        .code16
        .text
        .globl _start
_start:
        movw %cs, %ax
        movw %ax, %ds
        movw %ax, %es
        movw $hello, %ax
        movw %ax, %bp
        movw $13, %cx
        movw $0x1301, %ax
        movw $0x000c, %bx
        xorb %dl, %dl
        int $0x10
        jmp .

hello:
        .ascii "hello, world\n"

        .org _start + 510
        .byte 0x55, 0xaa

链接脚本如下boot.lds(链接脚本参考gnu ld的官方文档https://sourceware.org/binutils/docs-2.28/ld/index.html

OUTPUT_FORMAT(binary)
ENTRY(_start)
SECTIONS {
         . = 0x7c00;
         .text : {
               *(.text)
         }
}

写个简单的Makefile来自动化构建过程

boot.bin: boot.o boot.lds
        ld -Tboot.lds boot.o -o boot.bin

boot.o: boot.s
        as boot.s -o boot.o

这下输入简单的make就可以生成boot.bin了

$ make
as boot.s -o boot.o
ld -Tboot.lds boot.o -o boot.bin
$ xxd -a boot.bin
00000000: 8cc8 8ed8 8ec0 b81a 7c89 c5b9 0d00 b801  ........|.......
00000010: 13bb 0c00 30d2 cd10 ebfe 6865 6c6c 6f2c  ....0.....hello,
00000020: 2077 6f72 6c64 0a00 0000 0000 0000 0000   world..........
00000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

ok,跟之前的一模一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值