1

I have the following source snippet from a book that I'm reading now. So I created an asm file and typed exactly. Then used nasm command (nasm -f elf test.asm) then tried to compile into an executable file by using gcc (gcc test.o -o test) then I get the following error.

Error:

ld: warning: ignoring file test.o, file was built for unsupported file format which is not the architecture being linked (x86_64)

Source code:

[BITS 16]

[SECTION .text]

START:
    mov dx, eatmsg
    mov ah, 9
    int 21H

    mov ax, 04C00H
    int 21H

[SECTION .data]

eatmsg  db "Eat at Joe's!", 13, 10, "$"

I guess the source code is not compatible with current generation of CPUs (the book is old...).

How do I fix this source code to run under x86_64 CPUs ?

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
Moon
  • 22,195
  • 68
  • 188
  • 269
  • change to `[BITS 64]` ? But there are other problems as well, where did you set the entry point ? – phoxis Aug 31 '11 at 08:26
  • @Moon: `int 21h` is the interface for 16-bit DOS, 32-bit linux uses `int 80h` and x86_64 uses `syscall` (for a quick example see [here](http://stackoverflow.com/questions/7006926/learning-assembly-echo-program-name/7009032#7009032)) or search SO for one of the many other threads. – user786653 Aug 31 '11 at 15:50

3 Answers3

2

If you want to continue using that old book to learn the basics (which is just fine, nothing wrong with learning the basics/old way before moving on to modern OS), you can run it in DOSBox, or a FreeDOS VM.

Brian Knoblauch
  • 20,639
  • 15
  • 57
  • 92
  • 1
    // Thank you for the advice. Yes..that's my aim. I just can't leanr modern assembly language concepts without understanding why we're using current memory models... – Moon Aug 31 '11 at 17:00
1

That's a 16 bits code, it was made to create pure binary code and not executables. You cannot run it on modern OSs like Linux without heavy modifications. And btw, that's an MS-DOS assembly, which will not work for Linux anyway (using int 21h which are MS-DOS services).

If you want to learn assembly, I suggest getting a more modern book, or setting up a virtual machine in which to learn with your book (although learning 16-bits assembly is really not useful nowadays).

m0skit0
  • 25,268
  • 11
  • 79
  • 127
1

First of all the code contains interrupts which will work in real mode only and in DOS (int 21h with values in regs), and linux works in protected mode, you cannot call these interrupts directly.

Next the code is 16 bit code, to make it a 64 bit code you need [BITS 64]

Third you have no entry point to the code. To make one you can write a main function in C and then call the starting label as a function in the assembly code.

Have a look at this thing: PC Assembly Language by Paul A. Carter

phoxis
  • 60,131
  • 14
  • 81
  • 117
  • Interrupts can be used in protected mode as well. Check how Linux uses INT 0x80 for system calls (or at least it used it back on 2.4 kernels ^^) – m0skit0 Aug 31 '11 at 11:21
  • @m0skit0: they cannot be called directly, and also the `int 21h` is DOS interrupts, and the functions which is used will be only available in DOS. (`ah = 09h` with `ds:dx = address of char string` and `int 21h` will print the char string ($ terminated) ). – phoxis Aug 31 '11 at 16:10
  • Yes they can be called directly, don't be stubborn :P http://bluemaster.iu.hio.no/edu/dark/lin-asm/syscalls.html – m0skit0 Sep 01 '11 at 11:46
  • And also: http://en.wikipedia.org/wiki/Interrupt_descriptor_table#Protected_mode. And I know 21h is MSDOS service, as I stated on my answer. – m0skit0 Sep 01 '11 at 12:14
  • i know , they can be called, but in the above code in question, will simply not work. – phoxis Sep 01 '11 at 16:28