Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't include a file in NASM

Tags:

assembly

nasm

I try to include a file into my boot.asm file using

%include "input.asm"

But every time i try to compile it i get an error saying that nasm can't open the include file.
input.inc IS in the same directory as boot.asm I was looking here and on google for answers, but none has helped me.

Is there a special way include files should be compiled/formatted before including? Or is it just my nasm barking at me?

EDIT: Here's the code of include:

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

Error msg:

D:\ASMT\boot.asm:14: fatal: unable to open include file `input.asm'

like image 540
themorfeus Avatar asked Aug 06 '13 10:08

themorfeus


2 Answers

NASM provides the functionality for you to include other source files into your code. The method for achieving this is to use the %include directive, like so:

%include "input.asm"

The one caveat is that, NASM assumes all files are within the current working directory, e.g. the directory from which NASM is being run. If a file is passed to the %include directive, and the file cannot be located within the current working directory, NASM will return the following error:

fatal: unable to open include file

One solution, as already given in the accepted answer, is to specify any additionally referenced directories on the NASM command line, using the -i option. As an example, let us assume that an 'include' file, called 'print_string', is located within the directory 'procedure_library', and that this directory is not the NASM 'launch' directory. In this instance, we simply tell NASM where it can look for additional source files, like so:

nasm -i/home/user/asmwork/procedure_library/ -f elf64 -g -F dwarf sourecode.asm

*(a space between -i and the path name is allowed, and optional).

This is the preferred way for maintaining projects. However, this is rather a long command, as far as keystrokes are concerned. Although, the use of a Makefile would resolve this.

n.b. NASM does not understand the file naming conventions of the OS it is running on; the string you provide as an argument to the -i option will be parsed exactly as written. Therefore the trailing forward slash in the above example is necessary. Under Windows, a trailing backslash would be equally necessary.

Note also, the working directory, the directory from which you invoke NASM, will still need to contain your ‘main’ source code file, i.e. the command itself requires an input file as an argument. For instance, the above invocation, would still require ‘sourcecode.asm’ within the working directory, regardless of the additional -i option argument. If ‘sourcecode.asm’ was to reside in the optional directory ‘procedure_library’, NASM would return fatal: unable to open input file. The i option can be thought of as an %include file search argument.


Hard-Coding the File Path:

As an alternative to the given method, you can simply hard-code the file path, directly in the source file. Simply pass the relative, or absolute, path of the file to the %include directive. For example:

%include “/home/user/asmwork/procedure_library/input.asm”

Or, assuming your current working directory, from where you invoke NASM, is /home/user/asmwork/:

%include “/procedure_library/input.asm"


External Libraries:

Yet another option, and perhaps a better choice, for managing code complexity, would be to assemble the procedure library, externally, as its own object file, and link the two files when creating your final executable program. The latter, may also, make your procedures reusable across different programs.

Remember, you will need to provide the relative/absolute path, in your linker script, if the file to be linked is not within the working directory. Depending on the program you are using, you may or may not need to pass an additional argument during invocation. GNU linker, for instance, does not require any additional optional arguments, it simply asks that you pass a workable file path:

executable: sourcecode.o ld -o executable sourcecode.o /home/case/asmwork/procedure_library/input.o


Directive Location:

Although in this case it is absolutely fine to include the directive anywhere in your source code, it is generally good practice to use the %include directive near the top of your source code. Consider for instance if you were to include a macro file, well, in this instance NASM would hand you an error, along the lines of error: parser: instruction expected, as all macros must be fully defined before they are invoked.

like image 116
Andrew Hardiman Avatar answered Nov 18 '22 16:11

Andrew Hardiman


It seems that NASM include the files from the current directory :

Include files are searched for in the current directory (the directory you're in when you run NASM, as opposed to the location of the NASM executable or the location of the source file), plus any directories specified on the NASM command line using the -i option.

If you are executing NASM from another directory that D:\ASMT in your case, it is normal that it doesn't work.

Source : http://www.nasm.us/doc/nasmdoc4.html#section-4.6.1

like image 28
Pierre Fourgeaud Avatar answered Nov 18 '22 15:11

Pierre Fourgeaud