每当我用nasm boot.asm -o boot.bin
汇编脚本时,一切工作正常,除了字符串的位置偏离几个字节。
这是我的boot.asm
的样子:
[org 0x7C00]
[bits 16]
%include "stack.mac"
%include "string.mac"
%include "prepareenv.mac"
SECTION .text
GLOBAL _entry
_entry:
prepareenv _entry
PUSH message
PUSH strlen(message)
CALL _putchars
JMP $
string message, db "Running."
%include "putchars.asm"
times 510-($-$$) db 0
dw 0xAA55
这基本上就是我的putchars.asm
的样子(pushm和rpopm是宏,它们针对每个参数扩展为单独的push和pop。它们生活在stack.mac
中):
%ifndef _PUTCHARS_
%define _PUTCHARS_
%include "stack.mac"
; Arg 0: word(2) String address
; Arg 1: word(2) String length
_putchars:
PUSH EBP
MOV EBP, ESP
pushm AX, BX, CX, SI
MOV SI, [EBP + 4] ; Load string address
MOV CX, [EBP + 6] ; Load string length
MOV AH, 0x0E ; Print function
XOR BX, BX ; Zero BX
_putchars_print_loop:
MOV AL, [SI + BX] ; Move current character into string
CMP BX, CX ; Have we reached the full string length?
JE _putchars_ret ; If so, we can terminate
INT 0x10 ; Interrupt to BIOS
INC BX ; Increment BX
JMP _putchars_print_loop ; Repeat string loop
putchars_ret:
rpopm AX, BX, CX, SI
POP EBP
RET 4
%endif
这是我的string.mac
的样子:
%ifndef _STRING_
%define _STRING_
%macro string 2+
%{1}: %{2}
%{1}_length equ ($ - %{1})
%endmacro
%define strlen(name) name%+_length
%endif
prepareenv.mac
仅清除所有段寄存器。删除它不会改变任何东西,因此不重要。
当boot.asm
命中PUSH message
时,加载的地址是字符串实际在内存中开始之前的2个字节。无论字符串如何,这种情况都会发生,并且会在我包含的任何其他文件中发生(我有其他脚本,但是我将其剥离到此处发布的内容,并且具有相同的行为)
我怀疑是NASM中的错误,但是一种变通方法(如果可能)会很好。