Friday, April 17, 2009

 

Another Hello World program in assembly using puts

Program that displays 'hello world' using 'puts'.



extern puts ; make puts extern

section .data
msg db "Hello World",0

section .text
global main
BITS 32
main:
mov edi, msg
call puts
mov eax, 0
ret


There are minor changes from a standalone assembly program:
1) notice the extern declaration at the top. This declaration is so that the assembler does not complain about the 'call puts' instruction. The extern declaration just says that the function is declared elsewhere externally and the symbol 'puts' will be resolved during link time.


2) notice that '_start' symbol used in stand-alone assembly has been replaced by 'main'. This is necessary because this is not a stand-alone program and will be linked differently. Hence the _start symbol will be used by the linker elsewhere. If you use the _start symbol in your assembly program , then you will get an error during link time about multiple instances of _start.


3) mov edi, msg - moves the address of the msg buffer into edi.

4) call puts - call the putstring function which displays the message on the screen.



To assemble:
nasm -felf print.asm

To link:
gcc print.o -> this will resolve the symbol puts. So when the assembly code calls puts it will know which function to transfer control to.

Run:
a.out

------------------------------------------------------------------------------------------------------------------------------------
It is also useful to write a simple C program (for eg: hello world program), then use gcc with the -S switch to generate a .S file that contains the assembly. Keep in mind that the assembly generated thus uses the GNU assembly syntax.

if your c program is hello.c, you would do this to generate assembly
gcc hello.c -S

This will generate hello.s with the assembly code.

-----------------------------------------------------------------------------------------------

Thursday, April 16, 2009

 

CPUID - a simple example

CPUID is an instruction used to query processor specific information. The program below executes cpuid (leaf 0 ) that returns the vendor_id. On linux systems, /proc/cpuinfo will have the vendor_id.

%macro exitprog 0
mov ebx, 0
mov eax, 1
int 0x80
%endmacro

%macro showstring 3
mov eax, 4
mov ebx, %1
mov ecx, %2
mov edx, %3
int 0x80
%endmacro

section .data
here:
times 1 dd 0
eos:
times 1 dd 0
ebx_data dd 0
edx_data dd 0
ecx_data dd 0


segment .text
global _start
_start:
mov eax, 0
cpuid
mov dword [ebx_data], ebx
mov dword [edx_data], edx
mov dword [ecx_data], ecx
showstring 1,ebx_data,12
exitprog




Only the first 2 instructions are important. When cpuid is executed with a value of 0 in eax, it returns the vendor_id information in ebx,edx and ecx. The other instructions in the program merely display the string.

Notice the use of macros. The 'showstring' macro is the file-write system call used in the 'hello world' program. The 'exitprog' is the sys-exit system call.


Upon assembling and running the program the following output is obtained:
GenuineIntel

Please note that depending on the CPU, the output might vary.

On an AMD machine, the following output will be obtained:
AuthenticAMD

(In both cases the result is a 12-byte string contained in ebx,ecx and edx).

 

Hello World program in assembly

Why break the tradition?


Hello World program in assembly

section .data
msg db "Hello, world!",0
len equ $ - msg
section .text

global _start

_start:

mov edx,len
mov ecx,msg
mov ebx,1
mov eax,4 ; eax = 4 -> write to file
int 0x80

mov ebx,0

mov eax,1 ; eax = 1 -> exit
int 0x80


Key points:

The only interesting thing in the above program is the instruction int 0x80. int 0x80 is a linux system call. int 0x80 provides several different services. The type of service provided by the system call depends on the value in eax.

The first call to int 0x80 is with eax = 4. Eax=4 signifies 'write to a file'. Information about the file descriptor is provided in ebx register. In this case ebx = 1 which refers to stdout. Note that since we are writing to stdout , there is no need to open the file. ecx specifies the pointer to the data and edx specifies the length. The length is computed by subtracting the address of the first byte from the last byte.

For example, here is what the string layout will look like in memory (assume start address 0x100) :

0x100 -> 'H' 'e' 'l' 'l' 'o' ',' ' ' 'w' 'o' 'r' 'l' 'd' '!' <-0x10C

Each character is assigned a byte. So the starting address is 0x100 and the address of the byte after the last byte is 0x10d.

This is accomplished by the following line of code in the program:
//$ = 0x10d , msg= 0x100, so len = 0xd
len equ $ - msg


The second call to int 0x80 is with eax = 1. Eax=1 signifies the exit system call. Ebx contains the exit status. Think of it is exit(0) that you see in C programs.


Build the program:
I use the nasm assembler. Typically it comes with the linux distribution. just search for nasm and install.

Assemble:
1) nasm -felf hello.asm

will create hello.o in the same directory.

link:
2)ld hello.o

will create a.out

Run:
a.out

The output will be the 'hello , world!' string.

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]