i'm new to assembly language, I finished writing a simple program so i ran the follow commends
nasm -o learn.bin learn.asm
to assemble the code then
chmod +x learn.bin
and then finally to run it
./learn.bin
but the last returned an error
bash: ./learn.bin: cannot execute binary file
im running ubuntu with an atom intel CPU
any help would be awesome,
Thanks in advance
The error message sounds like you don't have a proper ELF executable header on it. It IS possible to assemble a file using Nasm's -f bin output format (the default, if you don't specify an output format). But it needs an ELF header stuffed into it.
The usual way would be nasm -f elf32 learn.asm (or perhaps -f elf64 if you've got 64-bit code). This "should" produce "learn.o", if all goes well. Then you've got to link this "linkable object" file using ld -o learn learn.o (add -melf-i386 if you're using 64-bit ld... which you probably are). Or, depending on the code, gcc -o learn learn.o (add -m32 for 64-bit gcc). I see that Jester has just told you that (in fewer words).
Here's an example of a file that "should" work the way you're trying to do it:
[map all hkhw.map] ; optional
;==========================
bits 32
ORIGIN equ 8048000h
org ORIGIN
section .text
code_offset equ 0
code_addr:
;--------------------------- ELF header----------------------
dd $464c457f,$00010101,0,0,$00030002,1,main,$34,0,0,$00200034,2,0
dd 1,code_offset,code_addr,code_addr,code_filez,code_memsz,5,4096
dd 1,data_offset,data_addr,data_addr,data_filez,data_memsz,6,4096
main:
;--------- your code goes here -------------------------------
push byte 4
pop eax
xor ebx, ebx
mov ecx, msg
push byte msg_len
pop edx
int 80h
push byte 1
pop eax
int 80h
;------------ constant data -----------------------
; (note that we're in .text, not .rdata)
align 4
;-------------------------------------------------------------
align 4
code_memsz equ $ - $$
code_filez equ code_memsz
data_addr equ (ORIGIN+code_memsz+4095)/4096*4096 + (code_filez % 4096)
data_offset equ code_filez
section .data vstart=data_addr
;------------ initialized data -------------
msg db "Hello from Nasm, all by itself!", 10
msg_len equ $ - msg
;---------------------------------------------------------------------------
idat_memsz equ $ - $$
bss_addr equ data_addr + ($ - $$)
section .bss vstart=bss_addr
;------------- uninitialized data ----------------------
;-------------------------------------------------
udat_memsz equ $ - $$
data_memsz equ idat_memsz + udat_memsz
data_filez equ idat_memsz
;========================
Well... that didn't format well. Probably unreadable. Try Nasm Forum. We can help you more if you post the code
You can't (normally) run plain binary files under linux. You'll have to create an ELF executable by first asking nasm to produce an object file and then using a linker. Note that your code should also of course be written for linux. There are plenty of examples on the internet, see this tutorial for example.
Related
I wrote a simple "Hello world" in assembly under debian linux:
; Define variables in the data section
SECTION .data
hello: db 'Hello world!',10
helloLen: equ $-hello
; Code goes in the text section
SECTION .text
GLOBAL _start
_start:
mov eax,4 ; 'write' system call = 4
mov ebx,1 ; file descriptor 1 = STDOUT
mov ecx,hello ; string to write
mov edx,helloLen ; length of string to write
int 80h ; call the kernel
; Terminate program
mov eax,1 ; 'exit' system call
mov ebx,0 ; exit with error code 0
int 80h ; call the kernel
After assembling
nasm -f elf64 hello.asm -o hello.o
ld -o hello hello.o.
I got a 9048 byte binary.
Then I changed two lines in the code: from .data to .DATA and .text to .TEXT:
SECTION .DATA
SECTION .TEXT
and got a 4856 byte binary.
Changing them to
SECTION .dAtA
SECTION .TeXt
produced a 4856 byte binary too.
NASM is declared to be a case-insensitive compiler. What is the difference then?
You're free to use whatever names you like for ELF sections, but if you don't use standard names, it becomes your responsibility to specify the section flags. (If you use standard names, you get to take advantage of default flag settings for those names.) Section names are case-sensitive, and .data and .text are known to NASM. .DATA, .dAta, etc. are not, and there is nothing which distinguishes these sections from each other, allowing ld to combine them into a single segment.
That automatically makes your executable smaller. With the standard flags for .text and .data, one of those is read-only and the other is read-write, which means that they cannot be placed into the same memory page. In your example program, both sections are quite small, so they could fit in a single memory page. Thus, using non-standard names makes your executable one page smaller, but one of the sections will have incorrect writability.
Ok.
So i have been messing around with Assembly, and i was wondering: just HOW does a linkes ELF64 File look like, and can i directly write a linked file in plain-text? (like create a file e.G "main", write the hex-values of the system-calls, and then run it without linking or assembling.)
I have tried objdump -x main but i don't think, this is the entire ELF-File, because there is too less information, as i think.
Here the output:
main: Dateiformat elf64-x86-64
Inhalt von Abschnitt .text:
4000b0 b8040000 00bb0100 0000b9d0 006000ba .............`..
4000c0 0c000000 cd80b801 000000cd 80 .............
Inhalt von Abschnitt .data:
6000d0 48454c4c 4f2c2057 4f524c44 HELLO, WORLD
my Assembler Code:
section .data
msg: db "HELLO, WORLD"
len: equ $-msg
section .text
;write
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, len
int 80h;
;quit
mov eax, 1
int 80h;
EDIT: My Compiler is finished now, I just stuck with assembler and let NASM/ld do the job
If you want to see the entire structure of your executable try:
objdump -D some_exe
and if you want to see your file in hex format do:
xxd some_exe
or
hexdump some_exe
can i directly write a linked file in plain-text?
Well... Theoretically you can if you know exactly the instructions of the executable and you write them in binary to a plaintext file.
For example, for any given executable exe_file you can do this:
touch temp_file plaintext_file
xxd -p exe_file > temp_file
xxd -p -r temp_file > plaintext_file
chmod u+x plaintext_file
The plaintext_file will be an executable exactly the same as your exe_file. If between steps 2 and 3 you modify the temp_file you are directly modifying the executable by hand, although it is not very likely to change something "specific", unless you have very deep understanding of elf64 format (which I don't and I'm not sure what can be achieved with this).
Note: I know step 1 is redundant, I used it for demonstrating that you are starting with 2 simple plaintext files.
I'm running on Ubuntu 12.10 64bit.
I am trying to debug a simple assembly program in GDB. However GDB's gui mode (-tui) seems unable to find the source code of my assembly file. I've rebuilt the project in the currently directory and searched google to no avail, please help me out here.
My commands:
nasm -f elf64 -g -F dwarf hello.asm
gcc -g hello.o -o hello
gdb -tui hello
Debug information seems to be loaded, I can set a breakpoint at main() but the top half the screen still says '[ No Source Available ]'.
Here is hello.asm if you're interested:
; hello.asm a first program for nasm for Linux, Intel, gcc
;
; assemble: nasm -f elf -l hello.lst hello.asm
; link: gcc -o hello hello.o
; run: hello
; output is: Hello World
SECTION .data ; data section
msg: db "Hello World",10 ; the string to print, 10=cr
len: equ $-msg ; "$" means "here"
; len is a value, not an address
SECTION .text ; code section
global main ; make label available to linker
main: ; standard gcc entry point
mov edx,len ; arg3, length of string to print
mov ecx,msg ; arg2, pointer to string
mov ebx,1 ; arg1, where to write, screen
mov eax,4 ; write command to int 80 hex
int 0x80 ; interrupt 80 hex, call kernel
mov ebx,0 ; exit code, 0=normal
mov eax,1 ; exit command to kernel
int 0x80 ; interrupt 80 hex, call kernel
This statement is false.
The assembler does produce line number information (note the -g -F dwarf) bits.
On the other hand he assembles what is obviously 32-bit code as 64 bits, which may or may not work.
Now if there are bugs in NASM's debugging output we need to know that.
A couple of quick experiments shows that addr2line (but not gdb!) does decode NASM-generated line number information correctly using stabs but not using dwarf, so there is probably something wrong in the way NASM generates DWARF... but also something odd with gdb.
GNU addr2line version 2.22.52.0.1-10.fc17 20120131, GNU gdb (GDB) Fedora (7.4.50.20120120-52.fc17)).
The problem in this case is that the assembler isn't producing line-number information for the debugger. So although the source is there (if you do "list" in gdb, it shows a listing of the source file - at least when I follow your steps, it does), but the debugger needs line-number information from the file to know what line corresponds to what address. It can't do that with the information given.
As far as I can find, there isn't a way to get NASM to issue the .loc directive that is used by as when using gcc for example. But as isn't able to take your source file without generating a gazillion errors [even with -msyntax=intel -mmnemonic=intel -- you would think that should work].
So unless someone more clever can come up with a way to generate the .loc entries which gives the debugger line number information, I'm not entirely sure how we can answer your question in a way that you'll be happy with.
I'm using ubuntu 64-bit and trying to run a .asm file on NASM. But it returns this error when I try to run the following code. What Iḿ trying to do is build an executable by compiling (or assembling) object file from the source
$ nasm -f elf hello.asm, and then after created the file hello.o is producing executable file itself from the object file by invoking linker
$ ld -s -o hello hello.o
This will finally build hello executable.
I'm following this tutorial http://www.faqs.org/docs/Linux-HOWTO/Assembly-HOWTO.html
Error:
i386 architecture of input file `hello.o' is incompatible with i386:x86-64 output
Code:
section .data ;section declaration
msg db "Hello, world!",0xa ;our dear string
len equ $ - msg ;length of our dear string
section .text ;section declaration
;we must export the entry point to the ELF linker or
global _start ;loader. They conventionally recognize _start as their
;entry point. Use ld -e foo to override the default.
_start:
;write our string to stdout
mov edx,len ;third argument: message length
mov ecx,msg ;second argument: pointer to message to write
mov ebx,1 ;first argument: file handle (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
;and exit
mov ebx,0 ;first syscall argument: exit code
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
This looks like it may be a simple mismatch between what's produced by nasm and what ld is trying to make:
i386 architecture of input file 'hello.o' is incompatible with i386:x86-64 output
In other words, nasm has produced a 32-bit object file hello.o and ld wants to take that and make a 64-bit executable file.
The nasm -hf command should give you the available output formats:
valid output formats for -f are (`*' denotes default):
* bin flat-form binary files (e.g. DOS .COM, .SYS)
ith Intel hex
srec Motorola S-records
aout Linux a.out object files
aoutb NetBSD/FreeBSD a.out object files
coff COFF (i386) object files (e.g. DJGPP for DOS)
elf32 ELF32 (i386) object files (e.g. Linux)
elf ELF (short name for ELF32)
elf64 ELF64 (x86_64) object files (e.g. Linux)
as86 Linux as86 (bin86 version 0.3) object files
obj MS-DOS 16-bit/32-bit OMF object files
win32 Microsoft Win32 (i386) object files
win64 Microsoft Win64 (x86-64) object files
rdf Relocatable Dynamic Object File Format v2.0
ieee IEEE-695 (LADsoft variant) object file format
macho32 NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files
macho MACHO (short name for MACHO32)
macho64 NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files
dbg Trace of all info passed to output stage
I see that your linked tutorial asks you to run:
nasm -f elf hello.asm
Try using:
nasm -f elf64 hello.asm
instead, and you may find ld stops complaining about the input file.
You need to tell the linker to produce an i386 output file, since you're writing i386 assembly:
ld -m elf_i386 -s -o hello hello.o
How to compile, link, and run a nasm app on Ubuntu 64 bit.
Install nasm:
sudo apt-get install nasm
Save a file with filename hello.asm:
section .data
hello: db 'Hello world!',10 ; 'Hello world!' plus a linefeed character
helloLen: equ $-hello ; Length of the 'Hello world!' string
; (I'll explain soon)
section .text
global _start
_start:
mov eax,4 ; The system call for write (sys_write)
mov ebx,1 ; File descriptor 1 - standard output
mov ecx,hello ; Put the offset of hello in ecx
mov edx,helloLen ; helloLen is a constant, so we don't need to say
; mov edx,[helloLen] to get it's actual value
int 80h ; Call the kernel
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return code of 0 (no error)
int 80h
Compile it:
nasm -f elf64 hello.asm
Link it:
ld -s -o hello hello.o
Run it
el#apollo:~$ ./hello
Hello world!
It works! What now? Request that your favorite compiler generate the assembly code that it would have been normally passed on to be converted to machine code. Google search: "convert php/java/python/c++ program to assembly"
Perspective: With all the people today attempting to tear down and get rid of general purpose computing for the general public, it's imperative that we teach the new students the concepts of how to build a general purpose turing machine from core principles, on up through the bare metal, then finally assemblers and programming languages.
How does learning assembly aid in programming?
99% of computer programs out there are 10 to 100 times slower than they could optimized to be only because programmers don't know what delays are being forced on them by their favorite high level compiler or interpreter.
A thorough understanding of the full stack here means you can coerce your programs to have that coveted property of only taking nanoseconds to do the job at hand. Time == money. So this knowledge of how to shun anything that takes longer than a few nanoseconds to complete saves time, and therefore money.
https://softwareengineering.stackexchange.com/questions/156722/how-does-learning-assembly-aid-in-programming
Is there a way to execute a flat binary image in Linux, using a syntax something like:
nasm -f bin -o foo.bin foo.asm
runbinary foo.bin
The Linux kernel can load several different binary formats - ELF is just the most common, though the a.out format is also pretty well known.
The supported binary formats are controlled by which binfmt modules are loaded or compiled in to the kernel (they're under the Filesystem section of the kernel config). There's a binfmt_flat for uClinux BFLT flat format binaries which are pretty minimal - they can even be zlib compressed which will let you make your binary even smaller, so this could be a good choice.
It doesn't look like nasm natively supports this format, but it's pretty easy to add the necessary header manually as Jim Lewis describes for ELF. There's a description of the format here.
Is there some reason you don't want to use "-f elf" instead of "-f bin"?
I think Linux won't run a binary that's not in ELF format. I can't find a tool that converts flat binaries to ELF, but you can cheat by putting the ELF information in foo.asm,
using the technique described here :
We can look at the ELF
specification, and
/usr/include/linux/elf.h, and
executables created by the standard
tools, to figure out what our empty
ELF executable should look like. But,
if you're the impatient type, you can
just use the one I've supplied here:
BITS 32
org 0x08048000
ehdr: ; Elf32_Ehdr
db 0x7F, "ELF", 1, 1, 1, 0 ; e_ident
times 8 db 0
dw 2 ; e_type
dw 3 ; e_machine
dd 1 ; e_version
dd _start ; e_entry
dd phdr - $$ ; e_phoff
dd 0 ; e_shoff
dd 0 ; e_flags
dw ehdrsize ; e_ehsize
dw phdrsize ; e_phentsize
dw 1 ; e_phnum
dw 0 ; e_shentsize
dw 0 ; e_shnum
dw 0 ; e_shstrndx
ehdrsize equ $ - ehdr
phdr: ; Elf32_Phdr
dd 1 ; p_type
dd 0 ; p_offset
dd $$ ; p_vaddr
dd $$ ; p_paddr
dd filesize ; p_filesz
dd filesize ; p_memsz
dd 5 ; p_flags
dd 0x1000 ; p_align
phdrsize equ $ - phdr
_start:
; your program here
filesize equ $ - $$
This image contains an ELF header,
identifying the file as an Intel 386
executable, with no section header
table and a program header table
containing one entry. Said entry
instructs the program loader to load
the entire file into memory (it's
normal behavior for a program to
include its ELF header and program
header table in its memory image)
starting at memory address 0x08048000
(which is the default address for
executables to load), and to begin
executing the code at _start, which
appears immediately after the program
header table. No .data segment, no
.bss segment, no commentary — nothing
but the bare necessities.
So, let's add in our little program:
; tiny.asm
org 0x08048000
;
; (as above)
;
_start: mov bl, 42 xor eax, eax inc eax int 0x80 filesize equ $ - $$
and try it out:
$ nasm -f bin -o a.out tiny.asm
$ chmod +x a.out
$ ./a.out ; echo $?
42
Minimally, Linux will need to figure out the format of the executable and it will get that from the first bytes. For example, if it's a script that will be #!, shebang. If it's ELF that will be 0x7F 'E' 'L' 'F'. Those magic numbers will determine the handler from a lookup.
So you're gonna need a header with a recognized magic number. You can get a list of shebang supported formats in /proc/sys/fs/binfmt_misc. Getting a list of native binary formats is (unfortunately) a little trickier.
bFLT may be a good choice. Indeed, it's a popular embedded executable format. But you can also squeeze ELF down quite far. This article got an ELF executable down to 45 bytes. That said, you'd be squeezing it down mostly by hand rather than by tool.