-2

我正在尝试编写一个小函数来在特定内存位置打印以空字符结尾或固定长度的字符串。这是我的代码:

vbrstart:
    xor eax, eax
    mov sp, 0x7a00
    mov bp, 0x6000
    mov ss, ax
    mov ds, ax
    mov es, ax
    xor ebx, ebx
    xor ecx, ecx
    push strict dword initializing
    push strict word 0x0000
    call printmsg
    jmp end


;push strict dword memloc
;push strict word length
;call printmsg
printmsg:
    pop strict dword [store_ret]
    mov [store_cx], cx
    mov [store_esi], esi
    pop cx
    pop esi
    push eax
    push ebx
    mov ah, 0x0E
    mov bx, 0x0007
    cmp cx, 0x0000
    je printnullterm
printgivenlen:
    lodsb
    cmp cx, 0x0000
    je printdone
    int 10h
    dec cx
    jmp printgivenlen
printnullterm:
    lodsb
    cmp al, 0x00
    je printdone
    int 10h
    jmp printnullterm
printdone:
    pop ebx
    pop eax
    mov esi, [store_esi]
    mov cx, [store_cx]
    push strict dword [store_ret]
    ret
printdata:
    store_cx dw 0
    store_esi dd 0
    store_ret dd 0

end:
    hlt
    jmp end

initializing db 10,13,'Initializing...',0

测试时,它会不确定地打印,并且不会在空字节处停止。我在哪里做错了?

4

2 回答 2

2

我发现您的代码存在 2 个问题:

  • 你已经编写了一个引导加载程序。这样的程序运行在 16 位实地址模式下。这意味着 a 的返回地址call将是一个单词,而不是您的代码所期望的dword 。

    printmsg:
    pop word [store_ret]
    
  • 您以冒险的方式设置堆栈。您需要首先更改 SS 寄存器,然后立即更改 SP 寄存器。

    xor ax, ax
    mov ss, ax      <<< Keep these together 
    mov sp, 0x7a00  <<< and in this order!
    

由于这是 16 位代码,因此无需push/pop地址作为双字。

push word initializing
...
pop si
于 2016-06-03T16:29:12.633 回答
1

您的堆栈未与所有推送和弹出正确对齐。检查参数传递及其在例程中的用法。首先,这里有一个提示:

vbrstart:
xor eax, eax
mov sp, 0x7a00
mov bp, 0x6000
mov ss, ax
mov ds, ax
mov es, ax
xor ebx, ebx
xor ecx, ecx
push strict dword initializing
push strict word 0x0000
call printmsg                   ; near call, only 16 bits ret addr stored
jmp end

;push strict dword memloc
;push strict word length
;call printmsg
printmsg:
    pop strict dword [store_ret]    ; pop dword (ret address + 16 bits- 1st argument)
    mov [store_cx], cx              ; store_cx = 0
    mov [store_esi], esi            ; store_esi = ??
    pop cx                          ; cx = initializing
    . . .
于 2016-06-03T16:18:22.273 回答