Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Linux Windows子系统上的Ubuntu上使用INT 0x80编译的可执行程序集不';不生产_Linux_Assembly_X86_Nasm_Windows Subsystem For Linux - Fatal编程技术网

在Linux Windows子系统上的Ubuntu上使用INT 0x80编译的可执行程序集不';不生产

在Linux Windows子系统上的Ubuntu上使用INT 0x80编译的可执行程序集不';不生产,linux,assembly,x86,nasm,windows-subsystem-for-linux,Linux,Assembly,X86,Nasm,Windows Subsystem For Linux,我一直在看汇编教程,我正在尝试运行hello world程序。我在Windows上的Ubuntu上使用Bash 以下是大会: section .text global _start ;must be declared for linker (ld) _start: ;tells linker entry point mov edx,len ;message length mov ecx,msg ;message to wr

我一直在看汇编教程,我正在尝试运行hello world程序。我在Windows上的Ubuntu上使用Bash

以下是大会:

section .text
    global _start     ;must be declared for linker (ld)

_start:             ;tells linker entry point
    mov edx,len     ;message length
    mov ecx,msg     ;message to write
    mov ebx,1       ;file descriptor (stdout)
    mov eax,4       ;system call number (sys_write)
    int 0x80        ;call kernel

    mov eax,1       ;system call number (sys_exit)
    int 0x80        ;call kernel

section .data
    msg db 'Hello, world!', 0xa  ;string to be printed
    len equ $ - msg     ;length of the string
我正在使用以下命令创建可执行文件:

nasm -f elf64 hello.asm -o hello.o
ld -o hello hello.o -m elf_x86_64
我使用以下方法运行它:

./hello
程序运行时似乎没有分段错误或错误,但不会产生任何输出


我不明白为什么代码不会产生输出,但我想知道在Windows上的Ubuntu上使用Bash是否与此有关?为什么它不产生输出?我如何修复它?

问题在于Ubuntu for Windows(Linux的Windows子系统)。它只支持64位
syscall
接口和系统调用机制

除了不能在64位二进制文件中使用
int0x80
(32位兼容性),Windows上的Ubuntu(WSL)也是如此


您需要从使用
int0x80
转换为。这并不难。一组不同的寄存器用于
系统调用
,系统调用号与其32位对应的寄存器不同。包含有关
syscall
接口、系统调用及其参数的信息<代码>系统写入和<代码>系统退出的定义如下:

同时使用
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位寄存器的
mov edi,1
mov rdi,1
具有相同的效果



这个答案不是编写64位代码的入门,只是关于使用
syscall
接口。如果您对编写调用C库的代码的细微差别感兴趣,并且符合64位System V ABI,那么有一些合理的教程可以帮助您入门。他讨论了堆栈对齐、红色区域、寄存器使用以及64位SystemV调用约定的基本概述。

问题在于Ubuntu for Windows(Linux的Windows子系统)。它只支持64位
syscall
接口和系统调用机制

除了不能在64位二进制文件中使用
int0x80
(32位兼容性),Windows上的Ubuntu(WSL)也是如此


您需要从使用
int0x80
转换为。这并不难。一组不同的寄存器用于
系统调用
,系统调用号与其32位对应的寄存器不同。包含有关
syscall
接口、系统调用及其参数的信息<代码>系统写入和<代码>系统退出的定义如下:

同时使用
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位寄存器的
mov edi,1
mov rdi,1
具有相同的效果



这个答案不是编写64位代码的入门,只是关于使用
syscall
接口。如果您对编写调用C库的代码的细微差别感兴趣,并且符合64位System V ABI,那么有一些合理的教程可以帮助您入门。他讨论了堆栈对齐、红色区域、寄存器使用以及64位SystemV调用约定的基本概述。

正如Ross Ridge在评论中指出的,编译64位时不要使用32位内核函数调用

编译32位或将代码“翻译”为64位系统调用。 下面是可能的情况:

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

正如Ross Ridge在评论中指出的,在编译64位时不要使用32位调用内核函数

编译32位或将代码“翻译”为64位系统调用。 下面是可能的情况:

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

在64位可执行文件中使用32位系统调用接口可能与此有关;可能他们也不支持64位可执行文件中的
int0x80
32位ABI。您的代码看起来可以在Linux上运行,在您的64位二进制文件中,.Oh,
msg
是否位于不适合32位的地址?这就可以解释了,尽管这不是通常的布局。尝试使用
strace./hello
或GDB单步查看
eax
中的错误返回值。在64位可执行文件中使用32位系统调用接口可能与此有关;可能他们也不支持64位可执行文件中的
int0x80
32位ABI。您的代码看起来可以在Linux上运行,在您的64位二进制文件中,.Oh,
msg
是否位于不适合32位的地址?这就可以解释了,尽管这不是通常的布局。尝试使用
strace./hello
或GDB单步查看
eax
中的错误返回值。我还想警告64b中的不同ABI,在64b中,将参数放入寄存器可能是最容易掌握的部分,但对于刚开始学习汇编的人来说,堆栈对齐和红色区域可能有点棘手。一般来说,我宁愿建议编译为32b二进制文件来回答这样的问题,但在windows中这不是一个选项,因为windows只支持64b linux)我还要警告64b中的不同ABI,在64b中,将参数放入寄存器可能是最容易掌握的部分,