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 0x80
až syscall
. 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