Haruskah saya mencoba melakukan masalah latihan dalam berkumpul? [Tutup]

9

Saya sedang melihat Project Euler Problem 48 :

Serial, 1 1 + 2 2 + 3 3 + ... + 10 10 = 10405071317.

Temukan sepuluh digit terakhir dari seri, 1 1 + 2 2 + 3 3 + ... + 1000 1000 .

Dengan Python saya bisa melakukan ini dengan satu baris:

sum((x**x for x in xrange(1,1001))

Tetapi setara perakitan ini akan menjadi 100 baris dan tantangan nyata.

Haruskah saya melakukan beberapa teka-teki ini dalam perakitan untuk mendapatkan wawasan tentang pemrograman tingkat rendah dan memahami bagaimana komputer sebenarnya bekerja?

Nishant
sumber
2
Jika Anda tidak tahu bagaimana memori bekerja, bagaimana Anda diharapkan menangani topik seperti pointer? Jika Anda tidak mengerti cara kerja komputer dan sistem operasi, bagaimana Anda bisa memprogram aplikasi?
Ramhound
Saya bisa membuat banyak abstraksi Ramhound, itulah sebabnya saya menanyakan hal ini kepada Anda. Saya mungkin tidak mengerti sepenuhnya pointer masih bisa melakukan sesuatu dalam pointer seperti bertukar yang masuk akal logis setelah Anda menganggap pointer menyimpan lokasi memori dari beberapa tipe data. Lagi Ramhound karena Anda menyarankan saya harus memahami hal-hal ini dapatkah Anda menyarankan apa yang luas topik yang harus saya baca? Bahasa Majelis dan sedikit COA akan bagus?
Nishant
Jika Anda tidak memahami sepenuhnya pointer, Anda akan menemukan bahwa itu menjadi kerugian besar di beberapa tempat.
David Thornley
3
Entah baris Python Anda menghitung x ^ 2 untuk x di 1..1000 (bukan x ^ x untuk x di 1..1000) atau python bahkan lebih ajaib daripada yang saya kira. :)
Ingo
Apakah fungsi "naik ke kekuatan" *dengan Python?

Jawaban:

1

Selain belajar perakitan, saya percaya bahwa mempelajari bagaimana bahasa tingkat rendah seperti C dikompilasi sangat berharga. Jadi jawaban saya adalah ya, tapi sekali lagi saya mungkin bias karena saya menikmati pemrograman tingkat rendah.

Misalnya, hanya memahami bagaimana pernyataan sederhana dikompilasi. Fungsi berikut,

int func(int val)
{
  int num = val * 5;
  return num;
}

... menjadi (setidaknya bit yang menarik):

movl    %edi, -20(%rbp)
movl    -20(%rbp), %edx
movl    %edx, %eax
sall    $2, %eax
addl    %edx, %eax

Kode ini mengambil argumen dari stack (val, parameter to func), menggesernya ke kiri 2 tempat (dikalikan dengan 2 ^ 2 atau 4) dan kemudian menambahkan nilai asli ke hasilnya. Hasil akhirnya adalah perkalian dengan 5. Contoh seperti ini menggambarkan sejumlah hal yang harus diperhatikan, seperti optimisasi kompiler. Alih-alih memanggil instruksi untuk secara langsung mengalikan dengan 5, itu menggeser dua tempat untuk mengalikan dengan 4 dan kemudian menambahkan nilai asli. Saya menemukan contoh seperti ini untuk sangat meningkatkan pemahaman saya tentang hal-hal di tingkat yang lebih rendah.

Hasilkan output assembler dari gcc dengan -Sopsi. Namun, perlu diketahui bahwa hasilnya akan bervariasi berdasarkan kompiler dan tingkat optimisasi.

Bagaimanapun, saya tidak berpikir menjadi programmer bahasa assembly sama dengan memahami assembly . Sekali lagi, saya merasa pemrograman dalam bahasa seperti C dan mengetahui bagaimana hal itu dimasukkan ke dalam kode mesin adalah praktik yang berharga.

Tuan Shickadance
sumber
11

Mungkin tidak perlu untuk benar-benar dapat menulis assembler (yang sebagian besar rincian inisialisasi dan konvensi pemanggilan untuk sistem Anda).

Perlu memahami beberapa, jika Anda mencoba men-debug sesuatu tanpa sumber.

TETAPI pasti layak untuk memahami mesin setidaknya pada level 'C' dan pointer (pada dasarnya assembler tingkat tinggi) sehingga Anda tahu mengapa menggabungkan string jutaan kali dalam satu lingkaran itu buruk.

Martin Beckett
sumber
Sebenarnya, beberapa implementasi yang relatif pintar dapat membuat for i in range(1000000): s = s + '.'tidak (jauh) lebih buruk daripada versi "dioptimalkan" yang saya gunakan kembali s. Demikian pula, beberapa perkembangan lainnya mematahkan asumsi yang masuk akal dengan pengetahuan C dan menganggap implementasi naif. Tetapi secara umum lebih bermanfaat daripada berbahaya. Ingatlah bahwa implementasi bahasa terkadang lebih pintar daripada Anda;)
2
@delnan -Aku hanya membutuhkan contoh singkat di mana sesuatu yang terlihat tidak berbahaya di Java / C # mungkin sangat mahal pada silikon. Saya secara khusus menjumpai banyak orang yang berpikir alokasi memori besar dan penyalinannya instan.
Martin Beckett
Aku benci mempercayai delnan itu :-)
Nishant
5

Pertanyaan bagus. Learning Assembly sudah pasti bagus dan sepadan dengan usaha.

  1. Pemahaman tingkat rendah seperti itu akan bermanfaat bagi pengembangan perangkat lunak tertanam
  2. Refactoring pada level rendah
  3. Ini akan membantu Anda dalam menggunakan debugger secara efektif
  4. Memberi Anda pemahaman tentang kode yang dibongkar untuk membantu dalam hal-hal seperti gua kode
Aditya P
sumber
2
Saya harus mencari codecave. Saya sering menggunakan ini, tetapi kami menyebutnya "Memutar" sekarang. research.microsoft.com/en-us/projects/detours
ProdigySim
1

Iya dan tidak.

Memang benar bahwa itu akan memberi Anda pemahaman yang lebih baik tentang apa yang kode Anda lakukan dan mengapa beberapa hal hanya merupakan ide buruk yang harus Anda pikirkan tentang upaya tersebut.

Belajar assembler bukanlah proyek akhir pekan, itu akan menghabiskan banyak waktu dan Anda perlu berpikir apakah waktu ini bisa dihabiskan dengan lebih baik.

Jika Anda tidak ke dalam kode yang dioptimalkan maka Anda mungkin tidak akan pernah melihat manfaat yang sama dengan upaya yang Anda lakukan.

Skeith
sumber
1

Saya melakukan banyak assembler ketika saya masih muda dan saya pikir itu tidak membantu memahami apa pun di luar assembler. Jika Anda melihat assembler modern itu semua hal-hal bahasa makro. Saya biasanya benci analogi, tapi begini: Apakah mengetahui cara kerja mesin membuat Anda menjadi pengemudi yang lebih baik?

Ian
sumber
Apakah mengetahui bagaimana mesin mobil bekerja membuat Anda menjadi pengemudi yang lebih baik? Tidak, tetapi itu membuat Anda pemilik mobil yang lebih baik, karena jika mesin rusak Anda dapat memperbaikinya.
Cameron Martin
Setuju, tetapi itu tidak membuat Anda menjadi pengemudi yang lebih baik, yang merupakan analogi yang saya gunakan. Dengan memperbaiki mesin sendiri, Anda tidak mendukung ekonomi yang lebih luas dengan menggunakan mekanik, ... Analogi memiliki batasan. Secara umum saya tidak akan pernah mencegah seseorang untuk belajar sesuatu jika mereka tertarik, tetapi saya pikir Anda harus pergi jauh ke dalam lubang kelinci untuk dapat menerapkannya dengan berguna pada bahasa tingkat yang lebih tinggi. Sebagai permulaan Anda perlu memahami optimisasi kompilasi yang digunakan oleh bahasa tertentu jika dikompilasi, atau penerjemah, atau jitter. Ini area yang luas.
Ian
1

Cara saya telah bekerja pada pemahaman assembler adalah dengan menulis program dalam bahasa tingkat yang lebih tinggi, kemudian mengganti bagian dengan (setidaknya mudah-mudahan) setara dengan traktat kode assembled yang fungsional. Ini berarti saya bisa menggunakan HLL untuk apa yang baik untuk mengatur dan memecahkan masalah tingkat tinggi - dan saya menggunakan asm untuk memukul logam.

(Ketika saya berbicara tentang program host yang ditulis dalam HLL, maksud saya C atau ObjC ketika saya mencoba untuk belajar asm x86_64, dan BASIC ketika saya sedang mengerjakan Z80, 6502 dan 6809 asm).


sumber