Windows上的Ubuntu上的Bash上的汇编编译可执行文件不产生输出 [英] Assembly compiled executable on Bash on Ubuntu on Windows doesn't produce output

查看:154
本文介绍了Windows上的Ubuntu上的Bash上的汇编编译可执行文件不产生输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在看汇编教程,我正在尝试运行一个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_writeSys_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,1mov 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.

这篇关于Windows上的Ubuntu上的Bash上的汇编编译可执行文件不产生输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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