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 !
Maciej Piechotka
July 3, 2008, July 03, 2008 20:41, permalink
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
Maciej Piechotka
July 8, 2008, July 08, 2008 17:27, permalink
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
Simple max() in Assembly