Вычислить максимальный эл-т массива В и отсортировать эл-ты массива А большие найденного максимума по убыванию
Вычислить максимальный эл-т массива В и отсортировать эл-ты массива А большие найденного максимума по убыванию
Вам результат ассемблером или машинным кодом?
Ассемблером,если можно
Цитата: Muvikk
Ассемблером,если можно
а ты за это миньетом будешь оплачивать или другим каким способом, милчел?
Код:
#include <stdio.h>
#ifdef __GNUC__
// ASM AT&T синтаксис для GCC
// максимум
int find_max(const int* ptr, size_t size) {
int imax = 0;
asm("movl %0, %%esi"::"d"(ptr));
asm("movl %0, %%ecx"::"d"(size));
asm("movl (%esi), %edx\n\t"
"next:\n\t"
"cmpl %edx, (%esi)\n\t"
"jl yes;\n\t"
"movl (%esi), %edx\n\t"
"yes:\n\t"
"addl $4, %esi\n\t"
"decl %ecx\n\t"
"jnz next;\n\t");
asm("movl %%edx, %0" :"=r"(imax));
return imax;
}
// сортировка по-убыванию
void desc_sort(int* ptr, size_t size) {
asm("movl %0, %%edi"::"d"(ptr));
asm("movl %0, %%edx"::"d"(size));
asm("xorl %ebx, %ebx\n\t"
"pushl %eax\n\t"
"outer:\n\t"
"movl %edi, %esi\n\t"
"movl %edx, %ecx\n\t"
"decl %ecx\n\t"
"inner:\n\t"
"movl (%esi), %eax\n\t"
"cmpl %eax, 4(%esi)\n\t"
"jl not_;\n\t"
"xchgl %eax, 4(%esi)\n\t"
"movl %eax, (%esi)\n\t"
"not_:\n\t"
"addl $4, %esi\n\t"
"decl %ecx\n\t"
"jnz inner;\n\t"
"incl %ebx\n\t"
"cmpl %edx, %ebx\n\t"
"jl outer;\n\t"
"popl %eax"
);
}
#else
// ASM INTEL-синтаксис для BCB, MSVC
// максимум
int find_max(const int* arr, size_t arr_size) {
int imax = 0;
__asm {
mov esi, arr
mov ecx, dword ptr arr_size
dec ecx
mov edx, [esi]
add esi, 4
next:
cmp [esi], edx
jl no;
mov edx, [esi]
no:
add esi, 4
loop next;
mov dword ptr imax, edx
};
return imax;
}
// сортировка по-убыванию
void desc_sort(int* arr, size_t arr_size) {
__asm {
mov esi, arr
mov edx, dword ptr arr_size
mov ecx, edx
push eax
outer:
mov edi, esi
mov ebx, edx
dec ebx
inner:
mov eax, [edi]
cmp [edi+4], eax
jl not_;
xchg eax, [edi+4]
mov [edi], eax
not_:
add edi, 4
dec ebx
jnz inner;
dec ecx
jnz outer;
pop eax
};
}
#endif
int main(void)
{
int arr[] = { 30, 93, 2, -77, 10, 100, 4 };
int i, size = sizeof(arr)/sizeof(arr[0]);
printf("max: %d\n", find_max(arr, size));
desc_sort(arr, size);
for(i = 0; i < size; i++)
printf("%d ", arr[i]);
putchar('\n');
return 0;
}
#ifdef __GNUC__
// ASM AT&T синтаксис для GCC
// максимум
int find_max(const int* ptr, size_t size) {
int imax = 0;
asm("movl %0, %%esi"::"d"(ptr));
asm("movl %0, %%ecx"::"d"(size));
asm("movl (%esi), %edx\n\t"
"next:\n\t"
"cmpl %edx, (%esi)\n\t"
"jl yes;\n\t"
"movl (%esi), %edx\n\t"
"yes:\n\t"
"addl $4, %esi\n\t"
"decl %ecx\n\t"
"jnz next;\n\t");
asm("movl %%edx, %0" :"=r"(imax));
return imax;
}
// сортировка по-убыванию
void desc_sort(int* ptr, size_t size) {
asm("movl %0, %%edi"::"d"(ptr));
asm("movl %0, %%edx"::"d"(size));
asm("xorl %ebx, %ebx\n\t"
"pushl %eax\n\t"
"outer:\n\t"
"movl %edi, %esi\n\t"
"movl %edx, %ecx\n\t"
"decl %ecx\n\t"
"inner:\n\t"
"movl (%esi), %eax\n\t"
"cmpl %eax, 4(%esi)\n\t"
"jl not_;\n\t"
"xchgl %eax, 4(%esi)\n\t"
"movl %eax, (%esi)\n\t"
"not_:\n\t"
"addl $4, %esi\n\t"
"decl %ecx\n\t"
"jnz inner;\n\t"
"incl %ebx\n\t"
"cmpl %edx, %ebx\n\t"
"jl outer;\n\t"
"popl %eax"
);
}
#else
// ASM INTEL-синтаксис для BCB, MSVC
// максимум
int find_max(const int* arr, size_t arr_size) {
int imax = 0;
__asm {
mov esi, arr
mov ecx, dword ptr arr_size
dec ecx
mov edx, [esi]
add esi, 4
next:
cmp [esi], edx
jl no;
mov edx, [esi]
no:
add esi, 4
loop next;
mov dword ptr imax, edx
};
return imax;
}
// сортировка по-убыванию
void desc_sort(int* arr, size_t arr_size) {
__asm {
mov esi, arr
mov edx, dword ptr arr_size
mov ecx, edx
push eax
outer:
mov edi, esi
mov ebx, edx
dec ebx
inner:
mov eax, [edi]
cmp [edi+4], eax
jl not_;
xchg eax, [edi+4]
mov [edi], eax
not_:
add edi, 4
dec ebx
jnz inner;
dec ecx
jnz outer;
pop eax
};
}
#endif
int main(void)
{
int arr[] = { 30, 93, 2, -77, 10, 100, 4 };
int i, size = sizeof(arr)/sizeof(arr[0]);
printf("max: %d\n", find_max(arr, size));
desc_sort(arr, size);
for(i = 0; i < size; i++)
printf("%d ", arr[i]);
putchar('\n');
return 0;
}
Код:
#===============================================================================
# По материалам:
# ~~~~~~~~~~~~~~~
# "Ассемблеры для Linux: Сравнение GAS и NASM"
#
# Параллельное рассмотрение GNU Assembler (GAS) и Netwide Assembler (NASM)
#
# Рэм Нараян, инженер-программист, IBM
#===============================================================================
// Сортировка массива целых чисел методом выбора
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
Компиляция и запуск:
as sort.s -o program.o; ld --dynamic-linker /lib/ld-linux.so.2 -lc -o program program.o; ./program
*/
/*******************************************************************************
*
* Пример представляет понятие функций, различных схем адресации памяти, стека и
* работы с функциями внешних библиотек. Программа сортирует массив из 10 чисел
* и с помощью функций puts и printf из внешней библиотеки C выводит содержимое
* несортированного и отсортированного массива. Для обеспечения модульности и
* представления понятия функций подпрограмма сортировки реализована отдельной
* процедурой, равно как и подпрограмма печати массива.
*
* Выполнение программы начинается с вызова puts после объявления данных. Функция
* puts выводит строку на консоль. Её единственным аргументом является адрес
* отображаемой строки, который передается путем добавления адреса строки в стек
* (pushl $usort_str). В GAS перед переменной usort_str должен указываться префикс
* $, после чего она трактуется как непосредственный адрес. Если префикс $ не
* указывается, то в стек вместо адреса помещаются фактические байты,
* представленные переменной памяти. Поскольку помещение переменной в стек
* фактически смещает указатель стека на двойное слово, указатель стека
* корректируется путем добавления к нему числа 4 (addl $4, %esp). Далее в стек
* помещаются три аргумента и вызывается функция print_array10. Внутри функции
* путем копирования esp в ebp создается локальный кадр стека. Вы также можете
* выделить пространство для локальных переменных, как это сделано в программе
* (subl $4, %esp). Это выполняется путем вычитания количества необходимых байт
* из esp. Значение esp – 4 представляет пространство из четырех байт, выделенное
* для локальной переменной, и такое выделение может продолжаться до тех пор,
* пока в стеке достаточно пространства для локальных переменных.
*
* Далее показан базовый режим косвенной адресации (movl 8(%ebp), %edx), названный
* так потому, что вы начинаете с базового адреса и добавляете к нему смещение для
* указания нужного адреса. В подпрограмме print_array10 вы можете увидеть еще один
* режим адресации, используемый после метки push_loop - movb (%ebx, %esi, 1), %al
* Такой режим адресации называется базово-индексной адресацией. В нем используются
* базовый адрес, индексный регистр и множитель. Поскольку определить количество
* байт, вызываемых из определенного места памяти, не представляется возможным,
* необходим способ определения объема адресуемой памяти. В GAS проблема решается
* с помощью множителя и использования в мнемонических командах суффикса b, w или
* l (например, movb). Общая форма базово-индексной адресации в GAS выглядит
* следующим образом:
*
* %сегмент:АДРЕС (, индекс, множитель) или
* %сегмент:(смещение, индекс, множитель), или
* %сегмент:АДРЕС(база, индекс, множитель).
*
* Конечный адрес рассчитывается по следующей формуле:
*
* АДРЕС или смещение + база + индекс * множитель.
*
* Таким образом, для того, чтобы обратиться к байту, используется множитель 1,
* для слова - 2 и для двойного слова - 4.
*
******************************************************************************/
.section .data
array:
.byte 89, 10, 67, 1, 4, 27, 12, 34, 86, 3
array_end:
.equ ARRAY_SIZE, array_end - array
array_fmt:
.asciz " %d"
usort_str:
.asciz "unsorted array:"
sort_str:
.asciz "sorted array:"
newline:
.asciz "\n"
.section .text
.globl _start
_start:
pushl $usort_str
call puts
addl $4, %esp
pushl $ARRAY_SIZE
pushl $array
pushl $array_fmt
call print_array10
addl $12, %esp
pushl $ARRAY_SIZE
pushl $array
call sort_routine20
# Корректировка указателя стека
addl $8, %esp
pushl $sort_str
call puts
addl $4, %esp
pushl $ARRAY_SIZE
pushl $array
pushl $array_fmt
call print_array10
addl $12, %esp
jmp _exit
print_array10:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %edx
movl 12(%ebp), %ebx
movl 16(%ebp), %ecx
movl $0, %esi
push_loop:
movl %ecx, -4(%ebp)
movl 8(%ebp), %edx
xorl %eax, %eax
movb (%ebx, %esi, 1), %al
pushl %eax
pushl %edx
call printf
addl $8, %esp
movl -4(%ebp), %ecx
incl %esi
loop push_loop
pushl $newline
call printf
addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
sort_routine20:
pushl %ebp
movl %esp, %ebp
# Выделение в стеке пространства под слово
subl $4, %esp
# Получение адреса массива
movl 8(%ebp), %ebx
# Запись размера массива
movl 12(%ebp), %ecx
decl %ecx
# Подготовка внешнего цикла
xorl %esi, %esi
outer_loop:
# Сохраняем индекс минимального элемента
movl %esi, -4(%ebp)
movl %esi, %edi
incl %edi
inner_loop:
cmpl $ARRAY_SIZE, %edi
jge swap_vars
xorb %al, %al
movl -4(%ebp), %edx
movb (%ebx, %edx, 1), %al
cmpb %al, (%ebx, %edi, 1)
jge check_next
movl %edi, -4(%ebp)
check_next:
incl %edi
jmp inner_loop
swap_vars:
movl -4(%ebp), %edi
movb (%ebx, %edi, 1), %dl
movb (%ebx, %esi, 1), %al
movb %dl, (%ebx, %esi, 1)
movb %al, (%ebx, %edi, 1)
incl %esi
loop outer_loop
movl %ebp, %esp
popl %ebp
ret
_exit:
movl $1, %eax
movl 0, %ebx
int $0x80
# По материалам:
# ~~~~~~~~~~~~~~~
# "Ассемблеры для Linux: Сравнение GAS и NASM"
#
# Параллельное рассмотрение GNU Assembler (GAS) и Netwide Assembler (NASM)
#
# Рэм Нараян, инженер-программист, IBM
#===============================================================================
// Сортировка массива целых чисел методом выбора
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
Компиляция и запуск:
as sort.s -o program.o; ld --dynamic-linker /lib/ld-linux.so.2 -lc -o program program.o; ./program
*/
/*******************************************************************************
*
* Пример представляет понятие функций, различных схем адресации памяти, стека и
* работы с функциями внешних библиотек. Программа сортирует массив из 10 чисел
* и с помощью функций puts и printf из внешней библиотеки C выводит содержимое
* несортированного и отсортированного массива. Для обеспечения модульности и
* представления понятия функций подпрограмма сортировки реализована отдельной
* процедурой, равно как и подпрограмма печати массива.
*
* Выполнение программы начинается с вызова puts после объявления данных. Функция
* puts выводит строку на консоль. Её единственным аргументом является адрес
* отображаемой строки, который передается путем добавления адреса строки в стек
* (pushl $usort_str). В GAS перед переменной usort_str должен указываться префикс
* $, после чего она трактуется как непосредственный адрес. Если префикс $ не
* указывается, то в стек вместо адреса помещаются фактические байты,
* представленные переменной памяти. Поскольку помещение переменной в стек
* фактически смещает указатель стека на двойное слово, указатель стека
* корректируется путем добавления к нему числа 4 (addl $4, %esp). Далее в стек
* помещаются три аргумента и вызывается функция print_array10. Внутри функции
* путем копирования esp в ebp создается локальный кадр стека. Вы также можете
* выделить пространство для локальных переменных, как это сделано в программе
* (subl $4, %esp). Это выполняется путем вычитания количества необходимых байт
* из esp. Значение esp – 4 представляет пространство из четырех байт, выделенное
* для локальной переменной, и такое выделение может продолжаться до тех пор,
* пока в стеке достаточно пространства для локальных переменных.
*
* Далее показан базовый режим косвенной адресации (movl 8(%ebp), %edx), названный
* так потому, что вы начинаете с базового адреса и добавляете к нему смещение для
* указания нужного адреса. В подпрограмме print_array10 вы можете увидеть еще один
* режим адресации, используемый после метки push_loop - movb (%ebx, %esi, 1), %al
* Такой режим адресации называется базово-индексной адресацией. В нем используются
* базовый адрес, индексный регистр и множитель. Поскольку определить количество
* байт, вызываемых из определенного места памяти, не представляется возможным,
* необходим способ определения объема адресуемой памяти. В GAS проблема решается
* с помощью множителя и использования в мнемонических командах суффикса b, w или
* l (например, movb). Общая форма базово-индексной адресации в GAS выглядит
* следующим образом:
*
* %сегмент:АДРЕС (, индекс, множитель) или
* %сегмент:(смещение, индекс, множитель), или
* %сегмент:АДРЕС(база, индекс, множитель).
*
* Конечный адрес рассчитывается по следующей формуле:
*
* АДРЕС или смещение + база + индекс * множитель.
*
* Таким образом, для того, чтобы обратиться к байту, используется множитель 1,
* для слова - 2 и для двойного слова - 4.
*
******************************************************************************/
.section .data
array:
.byte 89, 10, 67, 1, 4, 27, 12, 34, 86, 3
array_end:
.equ ARRAY_SIZE, array_end - array
array_fmt:
.asciz " %d"
usort_str:
.asciz "unsorted array:"
sort_str:
.asciz "sorted array:"
newline:
.asciz "\n"
.section .text
.globl _start
_start:
pushl $usort_str
call puts
addl $4, %esp
pushl $ARRAY_SIZE
pushl $array
pushl $array_fmt
call print_array10
addl $12, %esp
pushl $ARRAY_SIZE
pushl $array
call sort_routine20
# Корректировка указателя стека
addl $8, %esp
pushl $sort_str
call puts
addl $4, %esp
pushl $ARRAY_SIZE
pushl $array
pushl $array_fmt
call print_array10
addl $12, %esp
jmp _exit
print_array10:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %edx
movl 12(%ebp), %ebx
movl 16(%ebp), %ecx
movl $0, %esi
push_loop:
movl %ecx, -4(%ebp)
movl 8(%ebp), %edx
xorl %eax, %eax
movb (%ebx, %esi, 1), %al
pushl %eax
pushl %edx
call printf
addl $8, %esp
movl -4(%ebp), %ecx
incl %esi
loop push_loop
pushl $newline
call printf
addl $4, %esp
movl %ebp, %esp
popl %ebp
ret
sort_routine20:
pushl %ebp
movl %esp, %ebp
# Выделение в стеке пространства под слово
subl $4, %esp
# Получение адреса массива
movl 8(%ebp), %ebx
# Запись размера массива
movl 12(%ebp), %ecx
decl %ecx
# Подготовка внешнего цикла
xorl %esi, %esi
outer_loop:
# Сохраняем индекс минимального элемента
movl %esi, -4(%ebp)
movl %esi, %edi
incl %edi
inner_loop:
cmpl $ARRAY_SIZE, %edi
jge swap_vars
xorb %al, %al
movl -4(%ebp), %edx
movb (%ebx, %edx, 1), %al
cmpb %al, (%ebx, %edi, 1)
jge check_next
movl %edi, -4(%ebp)
check_next:
incl %edi
jmp inner_loop
swap_vars:
movl -4(%ebp), %edi
movb (%ebx, %edi, 1), %dl
movb (%ebx, %esi, 1), %al
movb %dl, (%ebx, %esi, 1)
movb %al, (%ebx, %edi, 1)
incl %esi
loop outer_loop
movl %ebp, %esp
popl %ebp
ret
_exit:
movl $1, %eax
movl 0, %ebx
int $0x80