京山游侠原文
在此:《使用 GCC 和 GNU Binutils 编写能在 x86 实模式运行的 16 位代码》
经过了一番调试,首先在freedos下qemu上通过: (首先是在Ubuntu14(64bit)上通过,apt-get install qemu,freedos镜像freedos.img见最下面的附件下载)
boot3.S( for freedos ):
.code16gcc
.global _start
.text
.align 4
_start:
pushw %ds
pushw %es
pushw %ss
movw %cs, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
pushw %sp
movw $stack, %ax
movw %ax, %sp
calll main
popw %sp
movw $stack, %sp
#movw $stack, %ax
#movw %ax, %sp
popw %ss
popw %es
popw %ds
movw $0x4c00, %ax
int $0x21 #return to DOS
message:
.string "Hello, world!\n\0"
.global display_str
display_str:
pushl %ebp
movl %esp, %ebp
and 0xfffffff0, %esp
pushl %ebp
pushl %ebx
pushl %ecx
pushl %edx
# movw $15, %cx
movw 0x0c(%ebp) , %cx # 15
movw 0x8(%ebp), %bp # movw $message, %bp
movw $0x1301, %ax
movw $0x000c, %bx
movw $0x0, %dx
int $0x10
popl %edx
popl %ecx
popl %ebx
popl %ebp
# movl %ebp, %esp
# popl %ebp
leavel
retl
.org 0x100
stack:
boot3.c( for freedos ):
__asm__(".code16gcc\n");
void display_str(char* str, short length);
void main()
{
char* str = "Hello world from C language.\n";
display_str(str, 29);
}
编译脚本如下:
make3.sh(for freedos):
#!/bin/bash
rm -f boot *.o *.out boot.img disassem.asm
as --32 boot3.S -o boot3_S.o
gcc -c -m32 boot3.c -o boot3_c.o
ld -Ttext 0x100 -m elf_i386 boot3_S.o boot3_c.o -o boot.elf
objdump -D -m i8086 boot.elf > disassem.asm
objcopy -j .text -j .rodata -O binary boot.elf boot.com
sudo mount -o loop freedos.img ./fda
sudo cp boot.com ./fda
sudo umount ./fda
qemu-system-i386 -fda freedos.img
然后改动试验在bochs下以软盘启动通过:(环境为Ubuntu18(64bit),apt-get install bochs bochs-x hexedit)
boot3.S( for bochs ):
.code16gcc
.global _start
.text
.align 4
_start:
pushw %ds
pushw %es
pushw %ss
movw %cs, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
pushw %sp
movw $stack, %ax
movw %ax, %sp
calll main
popw %sp
movw $stack, %sp
#movw $stack, %ax
#movw %ax, %sp
popw %ss
popw %es
popw %ds
# movw $0x4c00, %ax
# int $0x21 #return to DOS
hlt
message:
.string "Hello, world!\n\0"
.global display_str
display_str:
pushl %ebp
movl %esp, %ebp
and 0xfffffff0, %esp
pushl %ebp
pushl %ebx
pushl %ecx
pushl %edx
# movw $15, %cx
movw 0x0c(%ebp) , %cx # 15
movw 0x8(%ebp), %bp # movw $message, %bp
movw $0x1301, %ax
movw $0x000c, %bx
movw $0x0, %dx
int $0x10
popl %edx
popl %ecx
popl %ebx
popl %ebp
# movl %ebp, %esp
# popl %ebp
leavel
retl
.org 0x100
stack:
boot3.c( for bochs ):
__asm__(".code16gcc\n");
void display_str(char* str, short length);
void main()
{
char* str = "Hello world from C language.\n";
display_str(str, 29);
}
编译脚本如下:(注意然后要手动dd到空白软盘镜像和用hexedit改最后两个字节为0xAA55)
make3.sh(for bochs):
#!/bin/bash
rm -f boot *.o *.out boot.img disassem.asm
as --32 boot3.S -o boot3_S.o
gcc -c -m32 boot3.c -o boot3_c.o
ld -Ttext 0x7c00 -m elf_i386 boot3_S.o boot3_c.o -o boot.elf
objdump -D -m i8086 boot.elf > disassem.asm
objcopy -j .text -j .rodata -O binary boot.elf boot.out
dd if=/dev/zero of=boot.img bs=512 count=1
# dd if=boot.out of=boot.img bs=96 count=1 conv=notrunc #manually do this alike
# then edit the binary using e.g. hexedit, to add 0xAA55 (magic number)
运行bochs配置文件如下:
bochsrc(for bochs):
config_interface: textconfig
#display_library: sdl
#romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000
romimage: file=/usr/share/bochs/BIOS-bochs-latest
megs: 32
vgaromimage: file=/usr/share/vgabios/vgabios.bin
floppya: type=1_44, 1_44="boot.img", status=inserted
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=0, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
#ata0-master: type=disk, path="", mode=flat, cylinders=1024, heads=16, spt=63
ata0-slave: type=cdrom, path="/dev/cdrom", status=inserted
boot: floppy
#ips: 1000000
floppy_bootsig_check: disabled=0
log: /dev/stdout
panic: action=ask
error: action=report
info: action=report
debug: action=ignore
debugger_log: -
com1: enabled=1, dev=/dev/ttyS0
parport1: enabled=1, file="/dev/lp0"
sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=/dev/stdout, dmatimer=600000
vga_update_interval: 300000
keyboard_serial_delay: 250
keyboard_paste_delay: 100000
#floppy_command_delay: 500
mouse: enabled=1
private_colormap: enabled=0
#ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0
#keyboard_mapping: enabled=0, map=/usr/share/bochs/keymaps/x11-pc-de.map
#keyboard_type: mf
#user_shortcut: keys=ctrlaltdel
#magic_break: enabled=1
#cmosimage: cmos.img
#load32bitOSImage: os=nullkernel, path=../kernel.img, iolog=../vga_io.log
#load32bitOSImage: os=linux, path=../linux.img, iolog=../vga_io.log, initrd=../initrd.img
#i440fxsupport: enabled=1
#usb1: enabled=1, ioaddr=0xFF80, irq=10
#text_snapshot_check: enable
运行命令:bochs -f /root/bochsrc
(Ubuntu14上的bochs似乎不好用,即便apt-get install bochs-sdl。)
至此试验初步就告完成,但改动代码后还有问题。这里要感谢京山游侠的一文。
源文件打包在此:
freedos版:boot3_freedos_with_c_v0.8.tgz
和
bochs软盘启动版:boot3_bochs_with_c_v0.8.tgz ,
及
bochs配置文件bochsrc。