【问题标题】:Print string in real mode with FASM使用 FASM 在实模式下打印字符串
【发布时间】:2018-06-10 20:18:06
【问题描述】:

我正在尝试调用 BIOS 10h 中断函数 0Eh(电传输出)以在实模式下打印字符串(使用 QEMU 进行测试)。在 NASM 中我没有问题,程序正确打印字符串:

bits 16                             ; Use 16 bit code
section .text

boot:
    xor ax, ax                      ; Clear AX register
    mov ds, ax                      ; Clear DS register
    mov es, ax                      ; Clear ES register
    mov ss, ax                      ; Clear SS register
    mov si, hello                   ; Set SI to string
    mov ah, 0x0E                    ; Set function
.loop:
    lodsb                           ; Store character into AL
    or al, al                       ; Check for NULL end
    jz halt                         ; On NULL end
    int 0x10                        ; Call 10h interrupt
    jmp .loop                       ; Continue with next character
halt:
    cli
    hlt

hello: db "Hello, World!", 0

times 510 - ($-$$) db 0
dw 0xAA55

我按照以下命令制作软盘映像:

nasm -f elf64 boot.asm -o boot.o
ld -Ttext 0x7c00 boot.o -o boot.out
objcopy -O binary -j .text boot.out boot.bin
dd if=/dev/zero of=floppy.img bs=1024 count=720
dd if=boot.bin of=floppy.img conv=notrunc

但在 FASM强调的文本不能正确打印字符串:

format elf64
use16
section '.text'
org 0x0

boot:
    cld                             ; Clear direction flag
    xor ax, ax                      ; Clear AX register
    mov ds, ax                      ; Clear DS register
    mov es, ax                      ; Clear ES register
    mov ss, ax                      ; Clear SS register
    mov si, hello                   ; Set SI to string
    mov ah, 0x0E                    ; Set function
puts:
    lodsb                           ; Store character into AL
    or al, al                       ; Check for NULL end
    jz halt                         ; On NULL end
    int 0x10                        ; Call 10h interrupt
    jmp puts                        ; Continue with next character
halt:
    cli
    hlt

hello: db "Hello, World!", 0

times 510 - ($-$$) db 0
dw 0xAA55

并生成软盘映像:

fasm boot.asm boot.o
ld -Ttext 0x7c00 boot.o -o boot.out
objcopy -O binary -j .text boot.out boot.bin
dd if=/dev/zero of=floppy.img bs=1024 count=720
dd if=boot.bin of=floppy.img conv=notrunc

我错过了什么?

【问题讨论】:

  • 在您的 FASM 代码中使用 org 0x7c00 并从链接器命令中删除 -Ttext=0x7c00
  • -Ttext=0x7c00 不对 FASM 生成的 ELF 对象做任何事情,因为 FASM 与 NASM 不同,它不输出重定位条目,因此 LD 没有任何要修复的地址。告诉 FASM 使用 org 0x7c00 而不是 org 0x0 会让 FASM 输出正确的地址。
  • 如果您设置了 SS,您也应该设置 SP,以便 SS:SP 指向不会干扰代码操作的内存区域。
  • 感谢您的回答!

标签: assembly x86-16 bootloader fasm real-mode


【解决方案1】:

FASM 可以直接生成二进制和可执行文件。事实上,只有当您想将代码与一些高级语言一起使用时,才需要将 FASM 与目标文件和链接器一起使用。

实际上,FASM 的这一特性,再加上它的高度可移植性,使 FASM 成为操作系统开发人员最喜欢的汇编程序。

此外,BIOS 会将段寄存器设置为 0,并将 SP 设置为某个合理的值,因此您根本不需要设置它们。

这是您的代码,从不需要的部分中删除并带有适当的指令 (boot.asm):

        format binary as "bin"
        use16
        org     7c00h

boot:
        cld                     ; Clear direction flag

        mov     si, hello       ; Set SI to string
        mov     ah, 0x0E        ; Set function
puts:
        lodsb                   ; Store character into AL
        or      al, al          ; Check for NULL end
        jz      halt            ; On NULL end
        int     0x10            ; Call 10h interrupt
        jmp     puts            ; Continue with next character
halt:
        cli
        hlt

hello   db "Hello, World!", 0   ; don't use ":" for the data definitions.

        times 510 - ($-$$) db 0
        dw 0xAA55

编译后直接得到正确编译的二进制文件:boot.bin;

以下是运行引导扇区的最少命令:

$fasm boot.asm
$qemu-system-x86_64 -drive format=raw,media=disk,if=floppy,file=./boot.bin

请注意,您可以将二进制文件直接提供给 qemu 模拟器,而无需创建特殊的 floppy.img 文件。

【讨论】:

猜你喜欢
  • 2020-03-13
  • 2021-12-02
  • 2013-02-14
  • 1970-01-01
  • 1970-01-01
  • 2016-01-05
  • 2020-03-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多