NASM无法显示字符串

时间:2017-10-30 17:14:02

标签: assembly x86 kernel nasm osdev

我试图使用NASM将osdev c kernel中列出的准系统内核转换为汇编语言。 c版本工作得很好但不知何故我搞砸了asm。

程序首先使用bg和fg颜色初始化视频缓冲区,然后尝试将2行字符串写入视频缓冲区,从0xB8000开始,然后停止。

我尝试将背景颜色更改为蓝色,将forecolor更改为白色似乎正常工作,这表明对 _term_init 的调用确实有效。但除此之外,似乎没有任何东西像我希望的那样起作用。

我在汇编语言方面真的很新,希望那里的英雄可以拯救我的日子......

提前致谢。

以下是我的3个asm文件,使用以下命令编译:

nasm -felf32 [input.asm] -o [output.o]

然后使用

链接
i686-elf-gcc -T linker.ld -o myos.bin -ffreestanding -O2 -nostdlib [all object files] -lgcc

kernel.asm

[bits 32]

global kernel_main:function (kernel_main.end - kernel_main)

extern _term_writestring

extern _term_init

SECTION .text   align=16                                

kernel_main:; Function begin
        push    ebp
        mov     ebp, esp

        call    _term_init

        push    version
        call    _term_writestring
        add     esp, 4
        push    cpright
        call    _term_writestring
        add     esp, 4

        leave
        ret
.end:
; kernel_main End of function


SECTION .data   align=1                                     
version db "Simple OS Version 0.0.3\n", 0
cpright db "Sin Hing 2017 all rights reserved\n", 0

SECTION .bss    align=1                                 


SECTION .rodata align=4                                 

welcome_string:                                         ; byte
        db 53H, 69H, 6DH, 70H, 6CH, 65H, 20H, 4FH       ; 0000 _ Simple O
        db 53H, 20H, 56H, 65H, 72H, 73H, 69H, 6FH       ; 0008 _ S Versio
        db 6EH, 20H, 30H, 2EH, 30H, 2EH, 33H, 0AH       ; 0010 _ n 0.0.3.
        db 53H, 69H, 6EH, 20H, 48H, 69H, 6EH, 67H       ; 0018 _ Sin Hing
        db 20H, 61H, 6CH, 6CH, 20H, 72H, 69H, 67H       ; 0020 _  all rig
        db 68H, 74H, 73H, 20H, 72H, 65H, 73H, 65H       ; 0028 _ hts rese
        db 72H, 76H, 65H, 64H, 2EH, 0AH, 00H            ; 0030 _ rved...

term.asm

[bits 32]

VGA_WIDTH   equ 80
VGA_HEIGHT  equ 25

global term_buffer
global term_col
global term_row
global _term_init:function (_term_init.end - _term_init)                        ; void _term_init(void)
global _term_setcolor:function (_term_setcolor.end - _term_setcolor)            ; void _term_setcolor(char)
global _term_putentryat:function (_term_putentryat.end - _term_putentryat)      ; void _term_putentryat(char, char, dword, dword)
global _term_putchar:function (_term_putchar.end - _term_putchar)               ; void _term_putchar(char)
global _term_write:function (_term_write.end - _term_write)                     ; void _term_write(char*, dword)
global _term_writestring:function (_term_writestring.end - _term_writestring)   ; void _term_writestring(char*)

extern _strlen                                          ; near


SECTION .text   align=16
; Function _term_init: Initialize terminal
_term_init:; Function begin
        mov     dword [term_row], 0                     ; term_row = 0
        mov     dword [term_col], 0                     ; term_col = 0
        mov     byte [term_color], 7                    ; bg - 0(black), fg - 7(grey)
        mov     dword [term_buffer], 753664             ; [term_buffer] becoming origin or video mem
        movzx   edx, byte [term_color]                  ; set edx := term_color
        mov     eax, 753664                             ; 0xB8000 - hardware video memory
        shl     edx, 8                                  ; edx ([term_color]) << 8
        or      edx, 0x20                               ; 0x20=' '

.L1:    mov     word [eax], dx                          ; [eax] = ' '|bgfg
        add     eax, 2                                  ; 1 buffer = 1 word (2 byte)
        cmp     eax, 757664                             ; 80*25*2byte = 4000byte + origin
        jne     .L1

        ret
.end:
; term_init End of function


; Function _term_setcolor: Set terminal background and foreground color (fg | bg << 4)
_term_setcolor:; Function begin
        mov     eax, dword [esp+4]
        mov     byte [term_color], al

        ret
.end:
; term_setcolor End of function


; Function _term_putentryat: Write an entry to terminal buffer
_term_putentryat:; Function begin
        movzx   edx, byte [esp+8]                               ; color
        shl     edx, 8
        movzx   eax, byte [esp+4]                               ; c
        or      edx, eax

        mov     eax, dword [esp+16]                             ; y
        mov     ebx, VGA_WIDTH
        mul     ebx                                             ; y * 80
        add     eax, dword [esp+12]                             ; + x

        mov     ecx, dword [term_buffer]
        mov     word [ecx+eax*2], dx                            ; 2 byte per buffer

        ret
.end:
; term_putentryat End of function

; Function _term_putchar: write a char into terminal buffer
_term_putchar:; Function begin
        push    ebp
        mov     ebp, esp

        ; Call _term_putentryat
        mov     eax, dword [term_row]                           ; y
        push    eax
        mov     eax, dword [term_col]                           ; x
        push    eax
        movzx   eax, byte [term_color]
        push    eax
        movzx   eax, byte [ebp+8]                               ; c
        call    _term_putentryat
        add     esp, 16

        mov     eax, dword [term_col]                           ; if (++term_col == 80)
        inc     eax
        cmp     eax, VGA_WIDTH
        jne     .leave
        mov     dword [term_col], 0                             ; term_col = 0

        ; TODO: if reaching end of buffer, pop buffer top line into history, shift remaining
        ;       lines 1 row up.
        mov     eax, dword [term_row]                           ; if (++term_row == 25)
        inc     eax
        cmp     eax, VGA_HEIGHT
        jne     .leave
        mov     dword [term_row], 0                             ; term_col = 0

.leave: leave
        ret
.end:
; term_putchar End of function

; Function _term_write: Write input buffer to terminal buffer for [size] long, at current x, y
_term_write:; Function begin
        push    ebp
        mov     ebp, esp

        xor     eax, eax
        mov     ecx, dword [ebp+12]                     ; size
        mov     edx, dword [ebp+8]                      ; data (const char*)         

.for:   push    ecx                                     ; keep the counter
        movzx   ebx, byte [edx+eax]                     ; edx+eax == data[i]
        inc     eax
        push    ebx
        call    _term_putchar
        add     esp, 4
        pop     ecx                                    ; restore counter
        loop    .for

        leave
        ret                                             ; 0133 _ C3
.end:        
; term_write End of function

; Function _term_writesring: Write a string to terminal buffer at current x, y
_term_writestring:; Function begin
        push    ebp
        mov     ebp, esp

        mov     edx, dword [ebp+8]                      ; data (char*)
        push    edx
        call    _strlen
        add     esp, 4
        test    eax, eax                                ; leave if zero
        jz      .leave

        push    eax                                     ; size
        mov     edx, dword [ebp+8]
        push    edx
        call    _term_write
        add     esp, 8

.leave: leave
        ret
.end:
; term_writestring End of function


SECTION .data   align=1                                 ; section number 2, data


SECTION .bss    align=1                                 ; section number 3, bss
term_color:
        resb 1
term_buffer:
        resd 1
term_col:
        resw 1
term_row:
        resw 1

和最后一个stdlib.asm

[bits 32]

global _strlen:function (_strlen.end - _strlen)


SECTION .text   align=16

; Function _strlen: Measure the length of given string, in number of char. (ANSI)
_strlen: ; Function begin - _strlen(const char *)
        push    ebp
        mov     ebp, esp

        mov     edx, dword [ebp+8]                      ; const char * (param)
        xor     eax, eax                                ; comparand = 0       

.L1:    inc     eax
        cmp     byte [edx+eax-1], 0
        jne     .L1

        leave
        ret
.end:
; strlen End of function

;SECTION .data   align=1 noexecute                       ; section number 2, data

;SECTION .bss    align=1 noexecute                       ; section number 3, bss

编辑:添加链接描述文件以及如何运行 这是linker.ld

/* The bootloader will look at this image and start execution at the symbol
   designated as the entry point. */
ENTRY(_start)

/* Tell where the various sections of the object files will be put in the final
   kernel image. */
SECTIONS
{
    /* Begin putting sections at 1 MiB, a conventional place for kernels to be
       loaded at by the bootloader. */
    . = 1M;

    /* First put the multiboot header, as it is required to be put very early
       early in the image or the bootloader won't recognize the file format.
       Next we'll put the .text section. */
    .text BLOCK(4K) : ALIGN(4K)
    {
        *(.multiboot)
        *(.text)
    }

    /* Read-only data. */
    .rodata BLOCK(4K) : ALIGN(4K)
    {
        *(.rodata)
    }

    /* Read-write data (initialized) */
    .data BLOCK(4K) : ALIGN(4K)
    {
        *(.data)
    }

    /* Read-write data (uninitialized) and stack */
    .bss BLOCK(4K) : ALIGN(4K)
    {
        *(COMMON)
        *(.bss)
    }

    /* The compiler may produce other sections, by default it will put them in
       a segment with the same name. Simply add stuff here as needed. */
}

然后我使用grub-mkrescue和这个grub.cfg

创建一个multiboot iso
menuentry "myos" {
    multiboot /boot/myos.bin
}

最后,我使用qemu

测试它
qemu-system-i386 -cdrom myos.bin

0 个答案:

没有答案