GNU/Linux >> Znalost Linux >  >> Linux

Sestavení zkompilované spustitelné pomocí INT 0x80 na Ubuntu na Windows Subsystém pro Linux neprodukuje výstup

Problém je s Ubuntu pro Windows (Windows Subsystem for Linux). Podporuje pouze 64bitové syscall rozhraní a ne 32bitový x86 int 0x80 mechanismus systémového volání.

Kromě toho, že nelze použít int 0x80 (32bitová kompatibilita) v 64bitových binárních souborech nepodporuje Ubuntu ve Windows (WSL) ani spouštění 32bitových spustitelných souborů.

Musíte převést pomocí int 0x80syscall . Není to těžké. Pro syscall se používá jiná sada registrů a čísla systémového volání se liší od jejich 32bitových protějšků. Blog Ryana Chapmana obsahuje informace o syscall rozhraní, systémová volání a jejich parametry. Sys_write a Sys_exit jsou definovány takto:

%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     

Pomocí syscall také clobbers RCX a R11 registrů. Jsou považovány za nestálé. Nespoléhejte na to, že za syscall budou mít stejnou hodnotu .

Váš kód lze upravit na:

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

Poznámka:v 64bitovém kódu, pokud je cíl registr instrukce je 32bitový (jako EAX , EBX , EDI , ESI atd.) nula procesoru rozšíří výsledek do horních 32 bitů 64bitového registru. mov edi,1 má stejný účinek jako mov rdi,1 .

Tato odpověď nepředstavuje základ pro psaní 64bitového kódu, pouze o použití syscall rozhraní. Pokud vás zajímají nuance psaní kódu, který volá C knihovna a odpovídá 64bitovému System V ABI, existují rozumné návody, které vám pomohou začít, jako je návod NASM od Ray Toal. Probírá zarovnání zásobníku, červenou zónu, použití registrů a základní přehled konvence volání 64bitového systému V.


Jak již bylo uvedeno v komentářích Rosse Ridge, nepoužívejte 32bitové volání funkcí jádra, když kompilujete 64bit.

Buď zkompilujte pro 32bit, nebo „přeložte“ kód do 64bitových syscalls.Zde je, jak by to mohlo vypadat:

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. Kali na podsystému Windows pro Linux

  2. Co je lepší int 0x80 nebo syscall v 32bitovém kódu na Linuxu?

  3. Problémy s nastavením $PATH na Bash na Ubuntu na Windows (Linuxový subsystém)

  1. Vysvětlení subsystému Windows pro Linux, WSL a WSL2

  2. Omezení přístupu k systémovému volání pro aplikaci Linux

  3. Instalace Oracle JDK na subsystém Windows pro Linux

  1. Použití Windows Subsystem for Linux (WSL) od Sublime Text

  2. Připojení sdílené složky systému Windows v podsystému Windows pro Linux

  3. Wget error bash Windows Subsystém pro Linux