077b12f1039dceb830c2b83be8dcbd1b

Simple max() in Assembly

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#
# Max
# by Gnix <gnixmail@gmail.com>
# 
# Example:
#
# [gnix@localhost asm]$ as -o max.o max.s 
# [gnix@localhost asm]$ ld -dynamic-linker /lib/ld-linux.so.2 -o max -lc max.o
# [gnix@localhost asm]$ ./max 
# Max = 99 
#  


.section .data
output:
        .asciz "Max = %d \n"
values:
        .int 15, 23, 61, 35, 34, 21, 5, 99, 17, 52


.section .text
.globl _start
_start:
        movl values, %ebx             # move the first element of values in EBX
        movl $1, %edi                 # insert 1 in EDI

loop:
        movl values(, %edi,4), %eax   # copy the values[EDI] element in EAX
        cmp %ebx, %eax                # compare 

        cmova %eax, %ebx              # replace the value in EBX with EAX if the 
                                      # value is larger than what was originally 
                                      # in the EBX register

        inc %edi                      # increment EDI
        cmp $10, %edi                 # compare if EDI is 10 (number of elements)
        jne loop                      # if is no 10 loop

        pushl %ebx                    # push the max value
        pushl $output                 # push the output string
        call printf                   # call printf

        addl $8, %esp                 # add 8 to the ESP (extended stack pointer)

        pushl $0                      # insert 0 (as exit value)
        call exit                     # call exit

Refactorings

No refactoring yet !

1e8f141e7857d397d8020ed3b759e88a

Maciej Piechotka

July 3, 2008, July 03, 2008 20:41, permalink

No rating. Login to rate!

May be something like that:
- Avoid counting 'by hand'
- Iteration via esi/edi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
.section .data
output:
        .asciz "Max = %d \n"
values:
        .int 15, 23, 61, 35, 34, 21, 5, 99, 17, 52
values_end:

.section .text
.globl _start
_start:
        movl $0, %ebx
        movl $values, %esi
        movl $values_end, %edi
        subl $8, %esp

loop:
        movl (%esi), %eax
        cmp %ebx, %eax
        cmova %eax, %ebx

        addl $4, %esi
        cmp %esi, %edi
	jnz loop
loop_end:

	movl %ebx, 4(%esp)
	movl $output, (%esp)
	call printf
	addl $4, %esp

	movl $0, (%esp)
	call exit
1e8f141e7857d397d8020ed3b759e88a

Maciej Piechotka

July 8, 2008, July 08, 2008 17:27, permalink

No rating. Login to rate!

Modified version. May work better for modern CPU as it allows better pipelining - it should load data from memory [probably cache] into %ecx still operating on %eax. However the speed-up was not measured.

1
2
3
4
5
6
7
8
9
10
11
.section .data
output:
	.asciz "Max = %d \n"
values:
	.int 15, 23, 61, 35, 34, 21, 5, 99, 17, 52
values_end:
	.int -1 		# Allow pipelining
	
.section .text
.globl _start
_start:

%eax - the current value


            

          

%ebx - maximum


            

          

%ecx - value prefetched from memory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
	movl (values), %ebx
	movl (values+4), %ecx
	lea  (values+4), %esi
	lea  (values_end), %edi
	subl $8, %esp

loop:
	movl %ecx, %eax
	addl $4, %esi
	movl (%esi), %ecx
	
	cmp %ebx, %eax
	cmova %eax, %ebx

	cmp %esi, %edi
	jnz loop
loop_end:

	movl %ebx, 4(%esp)
	movl $output, (%esp)
	call printf
	addl $4, %esp

	movl $0, (%esp)
	call exit

Your refactoring





Format Copy from initial code

or Cancel