读京山游侠《使用 GCC 和 GNU Binutils 编写能在 x86 实模式运行的 16 位代码》


  
京山游侠原文在此:《使用 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.tgzbochs软盘启动版:boot3_bochs_with_c_v0.8.tgz , 及bochs配置文件bochsrc

  

More powered by