Итак, я написал функцию для сортировки десятичных чисел в Assembly (на самом деле в Arithmeti c Expression Compiler , но выводит сборку) с именем hybrid_sort
(если важно, код сборки имеется здесь ). Пример программы на C ++, в которой он используется, выглядит следующим образом:
/*
* Dakle, ovo ce biti omotac oko "hybrid_sort.aec" napisan u C++-u.
* "hybrid_sort.aec" sam po sebi nije program koji se moze pokrenuti,
* i zato cemo od C++ compilera (u ovom slucaju, GCC-a) traziti da
* napravi program unutar kojeg ce se "hybrid_sort.aec" moci pokrenuti,
* i, po mogucnosti, koji ce olaksati da ga testiramo. Drugim rijecima,
* ovo je program s kojim se "hybrid_sort.aec" moze staticki linkirati.
* */
#include <algorithm>
#include <chrono>
#include <fstream>
#include <iostream>
#include <iterator>
#include <random>
namespace AEC { // Da se razlikuju AEC-ove varijable od C++-ovih.
extern "C" { // Za GNU Linker (koji se dobije uz Linux i koristi ga GCC), AEC
// jezik je dijalekt C-a, a moj compiler je C compiler.
float result, originalni_niz[1 << 16], kopija_originalnog_niza[1 << 16],
pomocni_niz[1 << 16], i, gdje_smo_u_prvom_nizu, gdje_smo_u_drugom_nizu,
gornja_granica, donja_granica, sredina_niza,
stog_sa_sredinama_niza[1 << 10], stog_s_donjim_granicama[1 << 10],
stog_s_gornjim_granicama[1 << 10], vrh_stoga, pomocna_varijabla_za_zamijenu,
gdje_je_pivot, j, pivot, koliko_usporedbi_ocekujemo_od_QuickSorta,
koliko_usporedbi_ocekujemo_od_MergeSorta, razvrstanost,
Eulerov_broj_na_koju_potenciju, polinom_pod_apsolutnom,
razvrstanost_na_potenciju[8],
broj_vec_poredanih_podniza = 0, broj_obrnuto_poredanih_podniza = 0,
broj_pokretanja_MergeSorta = 0,
broj_pokretanja_QuickSorta =
0; // GNU linker omogucuje da se varijable ne deklariraju ne samo u
// razlicitim datotekama, nego i u razlicitim jezicima.
void hybrid_sort(); //".global hybrid_sort" iz "hybrid_sort.aec". U C++-u ga
// morate deklarirati da biste ga mogli koristiti. C++ nije
// kao JavaScript ili AEC u tom pogledu, C++ pokusava
// pronaci krivo natipkana imena varijabli i funkcija vec za
// vrijeme compiliranja.
}
} // namespace AEC
int main() {
std::cout << "Unesite koliko zelite da generirani niz bude dugacak."
<< std::endl;
int n;
std::cin >> n;
auto distribution = std::uniform_real_distribution<float>(-n, n);
auto generator =
std::default_random_engine(); // Moramo paziti da se generator
// pseudo-nasumicnih brojeva inicijalizira
// samo jednom, inace ce na Linuxu
// generirati obrnuto sortirani niz (a ne
// nasumicno poredan). To su nam spomenuli
// na fakultetu, no ja to nisam uzeo
// ozbiljno, pa sam se sada opekao.
std::cout << "Generiram niz od " << n << " nasumicnih decimalnih brojeva..."
<< std::endl;
std::generate_n(
&AEC::originalni_niz[0], n,
[&]() -> float { // C++-ove lambda funkcije, GCC ih podrzava od 2007, a
// komercijalni compileri jos od ranije. Nadajmo se da
// netko nece pokusati ukucati ovaj program u arhajski
// C++ compiler.
return distribution(generator);
});
std::copy_n(&AEC::originalni_niz[0], n, &AEC::kopija_originalnog_niza[0]);
AEC::gornja_granica = n;
AEC::donja_granica = 0;
AEC::vrh_stoga = -1;
std::cout << "Pokrecem potprogram u AEC-u..." << std::endl;
auto prvoVrijeme = std::chrono::high_resolution_clock::now();
AEC::hybrid_sort();
auto drugoVrijeme = std::chrono::high_resolution_clock::now();
std::cout << "Potprogram u AEC-u je zavrsio." << std::endl;
std::cout
<< "Detektirao je " << AEC::broj_vec_poredanih_podniza
<< " vec poredanih podnizova,\n"
<< AEC::broj_obrnuto_poredanih_podniza << " obrnuto poredanih podniza,\n"
<< AEC::broj_pokretanja_MergeSorta
<< " priblizno poredanih podnizova (pogodnih za MergeSort)\n i "
<< AEC::broj_pokretanja_QuickSorta
<< " nasumicno ispremjestanih podnizova.\nPokrecem C++-ov std::sort..."
<< std::endl;
auto treceVrijeme = std::chrono::high_resolution_clock::now();
std::sort(&AEC::kopija_originalnog_niza[0], &AEC::kopija_originalnog_niza[n]);
auto cetvrtoVrijeme = std::chrono::high_resolution_clock::now();
if (!std::equal(&AEC::originalni_niz[0], &AEC::originalni_niz[n],
&AEC::kopija_originalnog_niza[0])) {
std::cout << "C++-ov std::sort nije dobio isti rezultat!" << std::endl;
std::ofstream AECovRezultat("AECresult.txt");
std::ofstream CPPovRezultat("CPPresult.txt");
if (!AECovRezultat || !CPPovRezultat) {
std::cout << "Ne mogu otvoriti datoteke za ispis rezultata!" << std::endl;
return 2;
}
AECovRezultat << n << std::endl;
CPPovRezultat << n << std::endl;
std::copy_n(&AEC::originalni_niz[0], n,
std::ostream_iterator<float>(AECovRezultat, "\n"));
std::copy_n(&AEC::kopija_originalnog_niza[0], n,
std::ostream_iterator<float>(CPPovRezultat, "\n"));
AECovRezultat.close();
CPPovRezultat.close();
std::cout
<< "Rezultati su spremljeni u \"AECresult.txt\" i \"CPPresult.txt\""
<< std::endl;
return 1;
}
std::cout << "C++-ov std::sort dobio je isti rezultat." << std::endl;
std::cout << "C++-ov std::sort vrtio se "
<< (cetvrtoVrijeme - treceVrijeme).count()
<< " procesorskih taktova." << std::endl;
std::cout << "AEC-ov hybrid_sort vrtio se "
<< (drugoVrijeme - prvoVrijeme).count() << " procesorskih taktova."
<< std::endl;
return 0;
}
Я попытался создать программу на Rust, которая его вызывает. Вот main.rs
:
#[link(name = "hybrid_sort", kind = "static")]
mod aec {
extern "C" {
pub static mut originalni_niz: [f32; 65000];
pub static mut pomocni_niz: [f32; 65000];
pub static mut stog_sa_sredinama_niza: [f32; 1000];
pub static mut stog_s_donjim_granicama: [f32; 1000];
pub static mut stog_s_gornjim_granicama: [f32; 1000];
pub static mut razvrstanost_na_potenciju: [f32; 8];
pub static mut result: f32;
pub static mut i: f32;
pub static mut gdje_smo_u_prvom_nizu: f32;
pub static mut gdje_smo_u_drugom_nizu: f32;
pub static mut gornja_granica: f32;
pub static mut donja_granica: f32;
pub static mut sredina_niza: f32;
pub static mut vrh_stoga: f32;
pub static mut pomocna_varijabla_za_zamijenu: f32;
pub static mut gdje_je_pivot: f32;
pub static mut j: f32;
pub static mut pivot: f32;
pub static mut koliko_usporedbi_ocekujemo_od_QuickSorta: f32;
pub static mut koliko_usporedbi_ocekujemo_od_MergeSorta: f32;
pub static mut razvrstanost: f32;
pub static mut Eulerov_broj_na_koju_potenciju: f32;
pub static mut polinom_pod_apsolutnom: f32;
pub static mut broj_vec_poredanih_podniza: f32;
pub static mut broj_obrnuto_poredanih_podniza: f32;
pub static mut broj_pokretanja_MergeSorta: f32;
pub static mut broj_pokretanja_QuickSorta: f32;
pub fn hybrid_sort();
}
}
fn main() {
unsafe {
for i in 0..10 {
aec::originalni_niz[i] = (10 - i) as f32;
}
aec::gornja_granica = 10.;
aec::donja_granica = 0.;
aec::hybrid_sort();
for i in 0..10 {
println!("{}", aec::originalni_niz[i]);
}
}
}
Я ожидал, что он выведет:
1
2
3
4
5
6
7
8
9
10
Вот build.rs
:
extern crate cc;
fn main() {
cc::Build::new()
.file("src/hybrid_sort.s")
.compile("hybrid_sort");
}
Однако, когда я запускаю cargo build
, у меня такая ошибка:
error: linking with `cc` failed: exit code: 1
|
= note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.1fz15oxpkgtpgr14.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.1wwvstjn4dyc3alz.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.1yxj24e45v6q9q86.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.2mvtt0813pf07pog.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.2umen39fhcwjmc0z.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.3091dfbqk4lshnol.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.35ep7euvsenolvvb.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.42y3nx5hyg9yjwwt.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.495yr540a19kuq1o.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.4aci444gs0pfr5mo.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.56j8cnoxsa6jrgia.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.58nstkh897vbl3yr.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.h0bm2f7ve74u4yg.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.k67895wnew0zyg9.rcgu.o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.p5p3jfl4d3vuwrj.rcgu.o" "-o" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.349a1ajb22z1v56x.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps" "-L" "/home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/build/algorithms_by_length-ad934eefb132b896/out" "-L" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,--whole-archive" "-lhybrid_sort" "-Wl,--no-whole-archive" "-Wl,--start-group" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-dd4752c70d4ce71d.rlib" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-e04840eda0100e05.rlib" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-16bfb4d182748e63.rlib" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-185d9b81685a2f08.rlib" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-4806247fe4c34e64.rlib" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-879310dc3b96af61.rlib" "-Wl,--end-group" "/home/teo.samarzija/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-d0572f7a936161bf.rlib" "-Wl,-Bdynamic" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
= note: /usr/local/bin/ld: /home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/build/algorithms_by_length-ad934eefb132b896/out/libhybrid_sort.a(hybrid_sort.o): relocation R_X86_64_32S against undefined symbol `gornja_granica' can not be used when making a PIE object; recompile with -fPIE
/usr/local/bin/ld: /home/teo.samarzija/Documents/debug/algorithms_by_length/target/debug/deps/algorithms_by_length-17c6558ebb3996a0.58nstkh897vbl3yr.rcgu.o: in function `algorithms_by_length::main':
/home/teo.samarzija/Documents/debug/algorithms_by_length/src/main.rs:(.text._ZN20algorithms_by_length4main17h3070ff3b86a94a98E+0xb0): undefined reference to `donja_granica'
/usr/local/bin/ld: /home/teo.samarzija/Documents/debug/algorithms_by_length/src/main.rs:(.text._ZN20algorithms_by_length4main17h3070ff3b86a94a98E+0xb7): undefined reference to `gornja_granica'
/usr/local/bin/ld: /home/teo.samarzija/Documents/debug/algorithms_by_length/src/main.rs:(.text._ZN20algorithms_by_length4main17h3070ff3b86a94a98E+0x14c): undefined reference to `originalni_niz'
/usr/local/bin/ld: /home/teo.samarzija/Documents/debug/algorithms_by_length/src/main.rs:(.text._ZN20algorithms_by_length4main17h3070ff3b86a94a98E+0x2aa): undefined reference to `originalni_niz'
collect2: error: ld returned 1 exit status
Есть идеи, что происходит?