我尝试使用
将文件包含到我的boot.asm文件中%include "input.asm"
但每次我尝试编译它时都会收到错误消息,说nasm无法打开包含文件
input.inc
与boot.asm位于同一目录中
我在这里和谷歌寻找答案,但没有人帮助过我。
是否有一种特殊的方式包含文件应该在包含之前编译/格式化?或者只是我对我的咆哮?
编辑:这是包含的代码:
mov ax, 0x07C0 ; set up segments
mov ds, ax mov es, ax
mov si, welcome
call print_string
mov si, welcome2
call print_string
mov si, welcome4
call print_string
jmp .mainloop
%include 'input.asm'
mainloop: ;loop here
input.asm:
; ================
; calls start here
; ================
print_string:
lodsb ; grab a byte from SI
or al, al ; logical or AL by itself
jz .done ; if the result is zero, get out
mov ah, 0x0E
int 0x10 ; otherwise, print out the character!
jmp print_string
.done:
ret
get_string:
xor cl, cl
.loop:
mov ah, 0
int 0x16 ; wait for keypress
cmp al, 0x08 ; backspace pressed?
je .backspace ; yes, handle it
cmp al, 0x0D ; enter pressed?
je .done ; yes, we're done
cmp cl, 0x3F ; 63 chars inputted?
je .loop ; yes, only let in backspace and enter
mov ah, 0x0E
int 0x10 ; print out character
stosb ; put character in buffer
inc cl
jmp .loop
.backspace:
cmp cl, 0 ; beginning of string?
je .loop ; yes, ignore the key
dec di
mov byte [di], 0 ; delete character
dec cl ; decrement counter as well
mov ah, 0x0E
mov al, 0x08
int 10h ; backspace on the screen
mov al, ' '
int 10h ; blank character out
mov al, 0x08
int 10h ; backspace again
jmp .loop ; go to the main loop
.done:
mov al, 0 ; null terminator
stosb
mov ah, 0x0E
mov al, 0x0D
int 0x10
mov al, 0x0A
int 0x10 ; newline
ret
strcmp:
.loop:
mov al, [si] ; grab a byte from SI
mov bl, [di] ; grab a byte from DI
cmp al, bl ; are they equal?
jne .notequal ; nope, we're done.
cmp al, 0 ; are both bytes (they were equal before) null?
je .done ; yes, we're done.
inc di ; increment DI
inc si ; increment SI
jmp .loop ; loop!
.notequal:
clc ; not equal, clear the carry flag
ret
.done:
stc ; equal, set the carry flag
call print_string
ret
错误消息:
D:\ ASMT \ boot.asm:14:致命:无法打开包含文件`input.asm'
答案 0 :(得分:8)
似乎NASM
包含当前目录中的文件:
在当前目录中搜索包含文件(运行NASM时所在的目录,而不是NASM可执行文件的位置或源文件的位置),以及使用-i选项在NASM命令行上指定的任何目录。
如果您从NASM
的另一个目录中执行D:\ASMT
,则无法正常工作。
答案 1 :(得分:2)
NASM为您提供了将其他源文件包含到代码中的功能。实现此目的的方法是使用%include
指令,如下所示:
%include "input.asm"
一个警告是,NASM假定所有文件都在当前工作目录内,例如运行NASM的目录。如果将文件传递到%include
指令,并且该文件不能位于当前工作目录中,则NASM将返回以下错误:
fatal: unable to open include file
一种解决方案(已在接受的答案中给出)是使用-i
选项在NASM命令行上指定任何其他引用的目录。例如,让我们假设一个名为“ print_string”的“ include”文件位于目录“ procedure_library”内,并且该目录为 not NASM“ launch”目录。在这种情况下,我们仅告诉NASM在哪里可以找到其他源文件,就像这样:
nasm -i/home/user/asmwork/procedure_library/ -f elf64 -g -F dwarf sourecode.asm
* (-i
和路径名之间的空格是允许的,并且是可选的)。
这是维护项目的首选方式。但是,就击键而言,这是一个很长的命令。虽然,使用Makefile
可以解决此问题。
n.b。 NASM不了解其运行的操作系统的文件命名约定;您作为-i
选项的参数提供的字符串将完全按照编写的方式进行解析。因此,以上示例中的尾随正斜杠是必需的。在Windows下,同样需要反斜杠。
还请注意,工作目录(您从中调用NASM的目录)仍需要包含“主”源代码文件,即命令本身需要输入文件作为参数。例如,上述调用仍然需要工作目录中的“ sourcecode.asm”,而不管附加的-i
选项参数如何。如果“ sourcecode.asm”位于可选目录“ procedure_library”中,则NASM将返回fatal: unable to open input file
。 i
选项可以被视为%include 文件搜索参数。
............................................... ................................................... ................................................... .........
硬编码文件路径:
作为给定方法的替代方法,您可以直接在源文件中直接对文件路径进行硬编码。只需将文件的相对或绝对路径传递到%include
指令。例如:
%include “/home/user/asmwork/procedure_library/input.asm”
或者,假设您从中调用NASM的当前工作目录为/home/user/asmwork/
:
%include “/procedure_library/input.asm"
............................................... ................................................... ................................................... .........
外部库:
用于管理代码复杂性的另一种选择,也许是一个更好的选择,将是在外部将过程库组装为自己的目标文件,并在创建最终的可执行程序时链接这两个文件。后者可能还会使您的过程可在不同程序之间重用。
请记住,如果要链接的文件不在工作目录中,则需要在链接描述文件中提供相对/绝对路径。根据您使用的程序,在调用过程中可能需要也可能不需要传递其他参数。例如,GNU链接器不需要任何其他可选参数,它只是要求您传递一个可行的文件路径:
executable: sourcecode.o
ld -o executable sourcecode.o /home/case/asmwork/procedure_library/input.o
............................................... ................................................... ................................................... .........
指令位置:
尽管在这种情况下,可以在源代码中的任何位置包含该指令都是绝对好的,但是通常最好在源代码顶部附近使用%include
指令。例如,考虑是否要包含一个宏文件,在这种情况下,NASM会沿着error: parser: instruction expected
的行向您发送错误,因为在调用它们之前必须完全定义所有宏。