Anda memanggil scanf
dengan benar, menggunakan konvensi panggilan Sistem V x86-64. Ia meninggalkan nilai kembaliannya di eax
. Setelah konversi satu operan (%d
) berhasil, ia kembali dengan eax
= 1.
... correct setup for scanf, including zeroing AL.
call scanf ; correct
int 80h ; insane: system call with eax = scanf return value
Kemudian Anda menjalankan int 80h
, yang membuat panggilan sistem ABI lama 32-bit menggunakan eax=1
sebagai kode untuk menentukan yang panggilan sistem. (lihat Apa yang terjadi jika Anda menggunakan ABI Linux 32-bit int 0x80 dalam kode 64-bit?).
eax=1
/ int 80h
adalah sys_exit
di Linux. (unistd_32.h
memiliki __NR_exit
= 1). Gunakan debugger; itu akan menunjukkan kepada Anda instruksi mana yang membuat program Anda keluar.
Judul Anda (sebelum saya memperbaikinya) mengatakan Anda mengalami kesalahan segmentasi, tetapi saya mengujinya pada desktop x86-64 saya dan bukan itu masalahnya. Itu keluar dengan bersih menggunakan panggilan sistem keluar int 80h
. (Tetapi dalam kode yang melakukan segfault, gunakan debugger untuk mengetahui instruksi mana.) strace
mendekode int 0x80
panggilan sistem yang salah dalam proses 64-bit< /a>, menggunakan nomor panggilan syscall
64-bit dari unistd_64.h
, bukan nomor panggilan unistd_32.h
32-bit.
Kode Anda hampir berfungsi: Anda menggunakan int 0x80
ABI 32-bit dengan benar untuk sys_write
, dan hanya meneruskan argumen 32-bit. (Argumen penunjuk cocok dalam 32 bit karena kode/data statis selalu ditempatkan di ruang alamat virtual 2GiB rendah dalam model kode default pada x86-64. Tepat karena alasan ini, sehingga Anda dapat menggunakan instruksi ringkas seperti mov edi, formatin
untuk memasukkan alamat dalam register, atau gunakan sebagai perpindahan langsung atau perpindahan yang ditandatangani rel32.)
OTOH Saya pikir Anda melakukan itu karena alasan yang salah. Dan seperti yang ditunjukkan oleh @prl, Anda lupa mempertahankan penyelarasan tumpukan 16-byte.
Selain itu, menggabungkan panggilan sistem dengan fungsi C stdio biasanya merupakan ide yang buruk. Stdio menggunakan buffer internal daripada selalu membuat panggilan sistem pada setiap pemanggilan fungsi, sehingga segala sesuatunya bisa tampak tidak beres, atau read
dapat menunggu masukan pengguna ketika sudah ada data di buffer stdio untuk stdin
.
Lingkaran Anda juga rusak dalam beberapa hal. Anda sepertinya mencoba memanggil printf
dengan konvensi panggilan 32-bit (args di stack).
Bahkan dalam kode 32-bit, ini rusak, karena nilai pengembalian printf
ada di eax
. Jadi perulangan Anda tidak terbatas, karena printf
mengembalikan jumlah karakter yang dicetak. Itu setidaknya dua dari string format %d\n
, jadi dec rax
/ jnz
akan selalu melompat.
Di SysV ABI x86-64, Anda harus nol al
sebelum memanggil printf
(dengan xor eax,eax
), jika Anda tidak meneruskan argumen FP apa pun di register XMM. Anda juga harus memasukkan argumen di rdi
, rsi
, ..., seperti untuk scanf.
Anda juga add rsp, 8
setelah memasukkan dua nilai 8-byte, sehingga tumpukan bertambah selamanya. (Tetapi Anda tidak pernah kembali, jadi segfault akhirnya akan berada pada stack overflow, bukan saat mencoba kembali dengan rsp
tidak menunjuk ke alamat pengirim.)
Putuskan apakah Anda membuat kode 32-bit atau 64-bit, dan hanya salin/tempel dari contoh untuk mode dan OS yang Anda targetkan. (Perhatikan bahwa kode 64-bit dapat dan sering kali menggunakan sebagian besar register 32-bit.)
Lihat juga Merakit 32-bit binari pada sistem 64-bit (rantai alat GNU) (yang menyertakan bagian NASM dengan skrip asm-link
praktis yang merakit dan menghubungkan ke biner statis). Namun karena Anda menulis main
alih-alih _start
dan menggunakan fungsi libc, Anda sebaiknya menautkannya saja dengan gcc -m32
(jika Anda memutuskan untuk menggunakan kode 32-bit daripada mengganti bagian 32-bit dari program Anda dengan pemanggilan fungsi 64-bit dan konvensi panggilan sistem).
Lihat Apa saja konvensi pemanggilan untuk panggilan sistem UNIX & Linux di i386 dan x86-64.
person
Peter Cordes
schedule
20.11.2017
push
berargumentasi untukprintf
ke tumpukan? Sumber informasi apa yang Anda gunakan untuk melakukan hal seperti ini? (Saya curiga Anda mengubah kode/tutorial 32b menjadi 64b, tetapi itu tidak akan berhasil, ini lebih rumit... untuk saat ini, jika Anda memiliki sumber daya 32b asm yang bagus untuk belajar, akan lebih mudah untuk mengajar Anda bagaimana membangun biner 32b di bawah linux 64b dan bekerja dengannya). ... baik itu, atau sumber daya 64b Anda berkualitas rendah, dan coba yang lebih baik... - person Ped7g   schedule 20.11.2017printf
adalah salah satu yang lebih rumit untuk diperbaiki, karena memiliki jumlah argumen yang bervariasi, jadi Anda perlu mengetahui konvensi pemanggilan yang tepat di luar dasar. Anda juga dapat memeriksa tutorial ini (tampaknya menargetkan persis nasm+libc+32b dan tampaknya mendapat komentar yang baik): csee.umbc.edu/portal/help/nasm/sample.shtml Dan jika Anda baru memulai perakitan, saya akan melewatkan pemanggilan fungsi libc sepenuhnya, dan bermain-main dengan x86 murni instruksi (mengerjakan beberapa matematika), memeriksa nilai di debugger saja. - person Ped7g   schedule 20.11.2017printf
: stackoverflow.com/questions/47362660/ ... jangan ragu untuk bertanya di sana jika ada sesuatu yang tidak jelas atau berhasil untuk Anda. (tentang baris perintah yang panjang... terlihat mungkin membosankan, tapi saya menggunakan editor teks Kate dengan pengaturan metode build, jadi saya tidak keberatan dengan nama yang panjang itu... sekali lagi Anda juga dapat menyimpan perintah tersebut dalam skrip shell atau bahkan membuat file). Sayangnya saya tidak repot-repot menambahkan varian 64b. - person Ped7g   schedule 20.11.2017printf
dari perakitan.. maaf :D.. masih ada Ada banyak tutorial di Internet, dan saya terlalu lelah untuk menulis jawaban lengkapnya di sini. - person Ped7g   schedule 20.11.2017int 0x80
dalam mode 64-bit (stackoverflow.com /pertanyaan/46087730/). Sebenarnya masalahnya adalah tidak memutuskan apakah akan menggunakan panggilan sistem atau fungsi perpustakaan stdio. Dan parahnya, menggunakancall scanf
/int 80h
sehingga nomor syscall ditentukan oleh nilai kembalian scanf!!!! - person Peter Cordes   schedule 20.11.2017