この問題は、Ubuntu for Windows (Windows Subsystem for Linux) にあります。 64 ビットの syscall
のみをサポートします インターフェースであり、そうではありません 32 ビット x86 int 0x80
システムコール機構。
int 0x80
を使用できないことに加えて (32 ビット互換) 64 ビット バイナリでは、Ubuntu on Windows (WSL) は 32 ビット実行可能ファイルの実行もサポートしていません。
int 0x80
を使用してから変換する必要があります syscall
へ .難しくありません。 syscall
には別のレジスタ セットが使用されます。 また、システム コール番号は、対応する 32 ビットのものとは異なります。 Ryan Chapman のブログに syscall
に関する情報があります インターフェイス、システム コール、およびそれらのパラメータ。 Sys_write
および Sys_exit
は次のように定義されます:
%rax System call %rdi %rsi %rdx %r10 %r8 %r9 ---------------------------------------------------------------------------------- 0 sys_read unsigned int fd char *buf size_t count 1 sys_write unsigned int fd const char *buf size_t count 60 sys_exit int error_code
syscall
の使用 RCX も壊します そしてR11 登録します。それらは揮発性と見なされます。 syscall
の後に同じ値であることに依存しないでください .
コードは次のように変更できます:
section .text
global _start ;must be declared for linker (ld)
_start: ;tells linker entry point
mov edx,len ;message length
mov rsi,msg ;message to write
mov edi,1 ;file descriptor (stdout)
mov eax,edi ;system call number (sys_write)
syscall ;call kernel
xor edi, edi ;Return value = 0
mov eax,60 ;system call number (sys_exit)
syscall ;call kernel
section .data
msg db 'Hello, world!', 0xa ;string to be printed
len equ $ - msg ;length of the string
注:宛先の場合は 64 ビット コードで 命令のレジスタは 32 ビット (EAX など) 、EBX 、EDI 、ESI など) プロセッサ ゼロは、結果を 64 ビット レジスタの上位 32 ビットに拡張します。 mov edi,1
mov rdi,1
と同じ効果があります .
この回答は、64 ビット コードの記述に関する入門書ではなく、syscall
の使用に関するものです。 インターフェース。 C を呼び出すコードのニュアンスに興味がある場合は、 ライブラリであり、64 ビットの System V ABI に準拠しています。Ray Toal の NASM チュートリアルのように、始めるための合理的なチュートリアルがあります。彼は、スタック アライメント、レッド ゾーン、レジスタの使用法、および 64 ビット System V 呼び出し規則の基本的な概要について説明します。
Ross Ridge のコメントで既に指摘されているように、64 ビットをコンパイルするときは、カーネル関数の 32 ビット呼び出しを使用しないでください。
32 ビット用にコンパイルするか、コードを 64 ビット syscall に「変換」します。これは次のようになります。
section .text
global _start ;must be declared for linker (ld)
_start: ;tells linker entry point
mov rdx,len ;message length
mov rsi,msg ;message to write
mov rdi,1 ;file descriptor (stdout)
mov rax,1 ;system call number (sys_write)
syscall ;call kernel
mov rax,60 ;system call number (sys_exit)
mov rdi,0 ;add this to output error code 0(to indicate program terminated without errors)
syscall ;call kernel
section .data
msg db 'Hello, world!', 0xa ;string to be printed
len equ $ - msg ;length of the string