适用于Linux的Windows子系统上的Ubuntu上使用INT 0x80的程序集编译的可执行文件不会产生输出 [英] Assembly compiled executable using INT 0x80 on Ubuntu on Windows Subsystem for Linux doesn't produce output

查看:120
本文介绍了适用于Linux的Windows子系统上的Ubuntu上使用INT 0x80的程序集编译的可执行文件不会产生输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've been looking at a tutorial for assembly, and I'm trying to get a hello world program to run. I am using Bash on Ubuntu on Windows.

这里是程序集:

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

我正在使用以下命令创建可执行文件:

I am using these commands to create the executable:

nasm -f elf64 hello.asm -o hello.o
ld -o hello hello.o -m elf_x86_64

然后我使用以下命令运行它:

And I run it using:

./hello

然后该程序似乎没有分段错误或错误运行,但没有任何输出.

The program then seems to run without a segmentation fault or error, but it produces no output.

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

I can't figure out why the code won't produce an output, but I wonder if using Bash on Ubuntu on Windows has anything to do with it? Why doesn't it produce output and how can I fix it?

推荐答案

问题出在Windows的Ubuntu(Linux的Windows子系统)上.它仅支持64位的 syscall 接口和 32位x86 int 0x80 系统调用机制.

The issue is with Ubuntu for Windows (Windows Subsystem for Linux). It only supports the 64-bit syscall interface and not the 32-bit x86 int 0x80 system call mechanism.

除了无法在64位二进制文​​件中使用 int 0x80 (32位兼容性)之外,Windows上的Ubuntu(WSL)

Besides not being able to use int 0x80 (32-bit compatibility) in 64-bit binaries, Ubuntu on Windows (WSL) doesn't support running 32-bit executables either.

您需要从使用 int 0x80 转换为 syscall .不难 syscall 使用一组不同的寄存器,并且系统调用号与其32位对应号不同. Ryan Chapman的博客 syscall 界面上具有信息,系统调用,以及它们的参数. Sys_write Sys_exit 的定义方式如下:

You need to convert from using int 0x80 to syscall. It's not difficult. A different set of registers are used for a syscall and the system call numbers are different from their 32-bit counterparts. Ryan Chapman's blog has information on the syscall interface, the system calls, and their parameters. Sys_write and Sys_exit are defined this way:

%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 之后的相同值.

Using syscall also clobbers RCX and the R11 registers. They are considered volatile. Don't rely on them being the same value after the 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

注意:如果指令的目标寄存器是32位(如 EAX EBX EDI ESI 等),处理器零将结果扩展到高32位的64位寄存器. mov edi,1 mov rdi,1 具有相同的效果.

Note: in 64-bit code if the destination register of an instruction is 32-bit (like EAX, EBX, EDI, ESI etc) the processor zero extends the result into the upper 32-bits of the 64-bit register. mov edi,1 has the same effect as mov rdi,1.

这个答案不是编写64位代码的入门,仅关于使用 syscall 接口.如果您对编写调用 C 库并符合64位System V ABI的代码的细微差别感兴趣,可以使用一些合理的教程来入门,例如

This answer isn't a primer on writing 64-bit code, only about using the syscall interface. If you are interested in the nuances of writing code that calls the C library, and conforms to the 64-bit System V ABI there are reasonable tutorials to get you started like Ray Toal's NASM tutorial. He discusses stack alignment, the red zone, register usage, and a basic overview of the 64-bit System V calling convention.

这篇关于适用于Linux的Windows子系统上的Ubuntu上使用INT 0x80的程序集编译的可执行文件不会产生输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆