NASM我无法从.data节(DB / DW / DD ...)访问数据

时间:2019-11-11 21:39:04

标签: assembly x86 nasm

我正在尝试在x16玩具操作系统中进行nasm编程,但是无法获得DW / DB的正确值

当我尝试访问任何.data节的值,或更具体地说,访问任何DB / DW / DD / DQ值时,程序没有给出正确的值,就像DW的行为像RESW一样,我必须输入该值mov WORD [value_], 0x0100来存储所需的值,Nasm不会指出任何错误。

我尝试实施更正建议,但是最接近的是这个

bootloader.asm:

BITS 16

reset:

    xor ax,ax; AH = 0 = Reset floppy disk
    int 0x13;

    mov ax,0x07E0; When we read the sector

    mov es,ax; Set ES with 0x07e0
    xor bx,bx; Offset to read sector to

load_floppy:

    mov ah, 0x2
    mov al, 0x1
    mov ch, 0x0
    mov cl, 0x2
    mov dh, 0x0
    int 0x13

    jmp 0x07E0:0x0000; Jump to 0x7e0:0x0000

times 510 - ($ - $$) db 0; complete the bootsector with null
dw 0xAA55; end of bootsector

system.asm:

BITS 16

    text_string db 'This is my cool new OS!', 0

data: ; i found that code in http://mikeos.sourceforge.net/write-your-own-os.html

    mov ax, 07C0h       ; Set up 4K stack space after this bootloader
    add ax, 288     ; (4096 + 512) / 16 bytes per paragraph
    mov ss, ax
    mov sp, 4096

    mov ax, 07C0h       ; Set data segment to where we're loaded
    mov ds, ax

main:

    mov si, text_string ; Put string position into SI
    call print_string   ; Call our string-printing routine

    jmp $

print_string:           ; Routine: output string in SI to screen
    mov ah, 0Eh     ; int 10h 'print char' function

.repeat:

    lodsb           ; Get character from string
    cmp al, 0
    je .done        ; If char is zero, end of string
    int 10h         ; Otherwise, print it
    jmp .repeat

.done:
    ret

此gimme的输出疯狂,其中包含来自扩展的ascii的13个字符,其中一个是微笑表情符号

此代码可以正确输出,但即使我仅使用bootloader.asm:

BITS 16

text_string db 'Its ok here!', 0

start:

    mov ax, 07C0h       ; Set up 4K stack space after this bootloader
    add ax, 288     ; (4096 + 512) / 16 bytes per paragraph
    mov ss, ax
    mov sp, 4096

    mov ax, 07C0h       ; Set data segment to where we're loaded
    mov ds, ax

    mov si, text_string ; Put string position into SI
    call print_string   ; Call our string-printing routine

    jmp $           ; Jump here - infinite loop!

    print_string:           ; Routine: output string in SI to screen
        mov ah, 0Eh     ; int 10h 'print char' function

.repeat:

    lodsb           ; Get character from string
    cmp al, 0
    je .done        ; If char is zero, end of string
    int 10h         ; Otherwise, print it
    jmp .repeat

.done:
    ret

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

1 个答案:

答案 0 :(得分:3)

BIOS跳到您的代码时:

  • DL将包含您从中引导的任何存储设备的“ BIOS设备编号”。

  • 所有其他通用寄存器都保留为未初始化(“随机”)值

  • 所有段寄存器都保留为未初始化(“随机”)值

  • 将堆栈(SS:SP)设置为应该有效的值(以防在设置堆栈之前发生IRQ);但是您不知道在哪里(并且您将希望将更多数据加载到内存中,并且这样做时不会冒险覆盖堆栈)

  • CS:IP也将保留为未定义的值;

  • ,除了它们将工作到相同的0x00007C00物理地址(例如,可以是0x0000:0x7C00,可以是0x07C0:0x0000,并且不太可能像0x0700:0x0C00)之外

  • 标志可能是任何东西。直到您使用取决于方向标记的指令(例如“ rep stosw”),这通常才无关紧要。

  • 您的.BSS部分不会像您习惯的那样用零填充

  • 分段将使您感到困惑,并且使用非零分段将导致错误。要使用零段,您必须使用org 0x7C00

要解决所有问题,您需要执行以下操作:

    org 0x7C00

    ; More stuff here if you want...

main:
    xor ax,ax
    mov ds,ax
    mov es,ax
    cli                     ;Only for 8086
    mov ss,ax
    mov sp,0x7C00
    sti
    cld
    jmp far 0x0000:.here     ;Optional in theory, to set CS
.here:
    mov di,_BSS_START
    mov cx,_BSS_END - _BSS_START
    rep stosb                ;Fill BSS with zeros

    mov [bootDeviceNumber],dl


    ; More stuff here if you want... (at least a `jmp $` so you don't start executing data)