GNU/Linux >> Linux の 問題 >  >> Linux

Linux の Windows サブシステム上の Ubuntu で INT 0x80 を使用してアセンブリ コンパイルされた実行可能ファイルが出力を生成しない

この問題は、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 など) 、EBXEDIESI など) プロセッサ ゼロは、結果を 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

Linux
  1. Linux アプリケーションの syscall アクセスを制限する

  2. Linux の 32 ビット コードでは、int 0x80 と syscall のどちらが優れていますか?

  3. Linux の Windows サブシステムへの Oracle JDK のインストール

  1. Sublime Text から Windows Subsystem for Linux (WSL) を使用する

  2. Windows Subsystem for Linux での Windows 共有のマウント

  3. Wget エラー bash Linux 用 Windows サブシステム

  1. Linux用のWindowsサブシステムの説明、WSLおよびWSL2

  2. Linux 用 Windows サブシステムの Kali

  3. Windows (Linux サブシステム) の Ubuntu で Bash に $PATH を設定する際の問題