Programming in Assembly Language
After a long break I have started programming in pure assembly language again. My recent assembly experiences are to use short inline assembly in C/C++ code or looking at disassembly code during debugging. I have developed a little program to find out if an integer is a prime number or not.
Platforms and necessary tools
The source code is written with AT&T syntax which is most common in *nix world and uses gas (GNU assembler) on Linux. Intel syntax is used for MASM, TASM and NASM and most common in DOS and Windows. Intel syntax can also be compiled with gas-2.9.1. Have a look at gas manual.
You can have look at differences and similarities in AT&T and Intel syntax.
Following is the complete source code of my tiny program in prime.s file:
# Assembly source code to find out whether a number is prime or not
# hash sign (#) is used for comments in the source code
#next section is for data-variables,consts etc.
.section .data
msg_not_prime:
.ascii "Not a prime number\n"
len =. - msg_not_prime
msg_prime:
.ascii "A prime number\n"
len_prime = . - msg_prime
.section .text
.equ ST_ARGC_IN_FUNC, 8
.equ ST_NUMBER_IN_FUNC, 16
.equ ST_NUMBER, 8
.globl _start #entry point - define something like C main()
_start:
#Load the number from command line args
call args_to_int
addl $4, %esp # Free the stack allocated for the adress of
# instruction after return
#push the value in the stack, call prime function
#and it's the parameter
pushl %eax
call prime # Call a function
addl $4, %esp
cmpl $1, %ebx # Check the value in ebx; 1 for prime
je .is_prime
movl $len, %edx
movl $msg_not_prime, %ecx
movl $1, %ebx
movl $4, %eax
int $0x80
jmp .exit
.is_prime:
movl $len_prime, %edx
movl $msg_prime, %ecx
movl $1, %ebx
movl $4, %eax
int $0x80
.exit:
movl $0, %ebx
movl $1, %eax
int $0x80
#function to copy integer arg to eax
.type args_to_int, @function
args_to_int:
pushl %ebp
movl %esp, %ebp
xorl %eax, %eax
xorl %ebx, %ebx
xorl %ecx, %ecx
# return address + saved ebp ; number of args
movl ST_ARGC_IN_FUNC(%ebp), %ebx
cmpl $1, %ebx #if number of args is 1
jle .exit_args
movl ST_NUMBER_IN_FUNC(%ebp), %ebx # first arg is prog name
movl $10, %edi
movb (%ebx), %cl
cmpb $'-', %cl
jne .digit
incb %dh
incl %ebx
.next_digit:
mov (%ebx), %cl
.digit:
subb $'0', %cl
jb .done
cmpb $9, %cl
ja .done
mull %edi
addl %ecx, %eax
incb %dl
incl %ebx
jmp .next_digit
.done:
orb %dh, %dh
je .exit_args
negl %eax
.exit_args:
movl %ebp, %esp
popl %ebp
ret
# This function will store 1 in ebx if the number is prime
# otherwise, will store 0 (zero)
.type prime, @function
prime:
pushl %ebp
movl %esp, %ebp
movl $1, %ebx
movl 8(%ebp), %eax
cmpl $3, %eax
jle .end_loop
movl $2, %ecx
.loop_start:
movl $1, %ebx
cmpl 8(%ebp), %ecx
je .end_loop
movl $0, %ebx
movl 8(%ebp), %eax
movl $0, %edx
divl %ecx
cmpl $0, %edx
je .end_loop
incl %ecx
jmp .loop_start
.end_loop:
movl %ebp, %esp
popl %ebp
ret
How to generate program file:
gas (GNU assembler) is used to compile the souce and ld is used to link the compiled object code to generated executable. Both of them reside in GNU Binutils.
- Copy the source to a file named prime.s
- Compile the source
as -o prime.o prime.s
- Link the object file
ld -o prime prime.o
- Run the executable
./prime 7
It should give the following output:
A Prime Number
References:
- For everything to Program in assembly under Linux and Unix: http://www.linuxassembly.org/
- Programming from the Ground Up: http://savannah.nongnu.org/projects/pgubook/
- Art of Assembly.