Das Problem liegt bei Ubuntu für Windows (Windows-Subsystem für Linux). Es unterstützt nur die 64-Bit-Version von syscall
Schnittstelle und nicht das 32-Bit x86 int 0x80
Systemaufrufmechanismus.
Abgesehen davon, dass int 0x80
nicht verwendet werden kann (32-Bit-Kompatibilität) in 64-Bit-Binärdateien unterstützt Ubuntu unter Windows (WSL) auch nicht die Ausführung von ausführbaren 32-Bit-Dateien.
Sie müssen von der Verwendung von int 0x80
konvertieren bis syscall
. Es ist nicht schwer. Für syscall
wird ein anderer Registersatz verwendet und die Systemrufnummern unterscheiden sich von ihren 32-Bit-Gegenstücken. Ryan Chapmans Blog enthält Informationen zu syscall
Schnittstelle, die Systemaufrufe und ihre Parameter. Sys_write
und Sys_exit
sind folgendermaßen definiert:
%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
Mit syscall
verprügelt auch RCX und das R11 registriert. Sie gelten als volatil. Verlassen Sie sich nicht darauf, dass sie nach syscall
denselben Wert haben .
Ihr Code könnte wie folgt geändert werden:
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
Hinweis:im 64-Bit-Code, wenn das Ziel Register einer Anweisung ist 32-Bit (wie EAX , EBX , EDI , ESI usw.) erweitert die Prozessor-Null das Ergebnis in die oberen 32 Bit des 64-Bit-Registers. mov edi,1
hat die gleiche Wirkung wie mov rdi,1
.
Diese Antwort ist keine Einführung in das Schreiben von 64-Bit-Code, sondern nur in die Verwendung von syscall
Schnittstelle. Wenn Sie an den Nuancen des Schreibens von Code interessiert sind, der das C aufruft Bibliothek und entspricht dem 64-Bit-System V ABI gibt es vernünftige Tutorials, um Ihnen den Einstieg zu erleichtern, wie das NASM-Tutorial von Ray Toal. Er erläutert die Stack-Ausrichtung, die rote Zone, die Registernutzung und einen grundlegenden Überblick über die 64-Bit-System-V-Aufrufkonvention.
Wie bereits in Kommentaren von Ross Ridge erwähnt, verwenden Sie keine 32-Bit-Aufrufe von Kernel-Funktionen, wenn Sie 64-Bit kompilieren.
Kompilieren Sie entweder für 32-Bit oder "übersetzen" Sie den Code in 64-Bit-Systemaufrufe. So könnte das aussehen:
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