【问题标题】:Input output in x64 assemblyx64 汇编中的输入输出
【发布时间】:2017-05-20 02:32:49
【问题描述】:

我如何获得我完全不理解的输入和输出,并且在任何地方都没有找到一个简单的示例 我唯一拥有的是:

我在 Visual Studio 中使用 masm

; get a write handle
MOV rcx, STD_OUTPUT_HANDLE
CALL    GetStdHandle
MOV whandle, eax            ; write handle

; get a read handle
MOV rcx, STD_INPUT_HANDLE
CALL    GetStdHandle
MOV rhandle, eax            ; read handle`

【问题讨论】:

  • 在什么操作系统下?
  • 我在 Visual Studio 中使用 Windows 10

标签: assembly 64-bit masm


【解决方案1】:

这是高度特定于操作系统的。为此,您需要调用操作系统提供的 API 函数。显然,从问题中的代码以及您的评论来看,您的目标是 Windows,因此您需要在 Microsoft 的文档中查看允许您读取和/或写入控制台的 Windows API 函数。您已经找到了GetStdHandle 函数;其他必需的功能将记录在同一位置。

具体来说,您可能正在寻找ReadConsoleWriteConsole,尽管还有很多专门用于控制台I/O 的函数。您可以在 this website 上找到有关如何从 C 调用这些函数的简短教程。

您应该能够将该 C 代码翻译成汇编语言。任何 Windows API 函数都可以像 GetStdHandle 一样从汇编语言中调用,遵循 standard Windows 64-bit calling convention。如果您在将 C 转换为汇编时遇到困难,您总是可以用 C 编写代码,通过编译器运行它,然后查看反汇编列表以了解它应该如何完成。 p>

这是一个简单的例子。首先,它使用WriteConsole 将一些指令文本写入控制台,并通过调用GetStdHandle 获得输出句柄。然后,它使用ReadConsole 将一些文本读入缓冲区,并使用通过调用GetStdHandle 获得的输入句柄。最后,它通过调用WriteConsole 在控制台中重复该文本。

; L"Type some text:\n"
szInstruction DB 'T', 00H, 'y', 00H, 'p', 00H, 'e', 00H, ' ', 00H,
              DB 's', 00H, 'o', 00H, 'm', 00H, 'e', 00H, ' ', 00H,
              DB 't', 00H, 'e', 00H, 'x', 00H, 't', 00H, ':', 00H,
              DB 0AH, 00H, 00H, 00H


MyFunction PROC
    ; Allocate space on the stack
    sub  rsp, 264

    ; WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
    ;               L"Type some text:\n",
    ;               16,
    ;               address of DWORD-sized variable on stack,
    ;               NULL);
    mov  ecx, -11                     ; STD_OUTPUT_HANDLE
    call GetStdHandle

    mov  rcx, rax                     ; handle was returned in RAX
    lea  rdx, OFFSET szInstruction
    mov  r8d, 16
    lea  r9, QWORD PTR [rsp+272]
    mov  QWORD PTR [rsp+32], 0
    call WriteConsoleW

    ; ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE),
    ;              address of string buffer on stack,
    ;              100,
    ;              address of DWORD-sized variable on stack,
    ;              NULL);
    mov  ecx, -10                     ; STD_INPUT_HANDLE
    call GetStdHandle

    mov  rcx, rax                     ; handle was returned in RAX
    lea  rdx, QWORD PTR [rsp+48]
    mov  r8d, 100
    lea  r9, QWORD PTR [rsp+272]
    mov  QWORD PTR [rsp+32], 0
    call ReadConsoleW

    ; WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
    ;               address of string buffer on stack,
    ;               number of chars read (from DWORD-sized variable written into by ReadConsoleW),
    ;               address of DWORD-sized variable on stack,
    ;               NULL);
    mov  ecx, -11                     ; STD_OUTPUT_HANDLE
    call GetStdHandle

    mov  rcx, rax                     ; handle was returned in RAX
    lea  rdx, QWORD PTR [rsp+48]
    mov  r8d, DWORD PTR [rsp+272]
    lea  r9, QWORD PTR [rsp+272]
    mov  QWORD PTR [rsp+32], 0
    call WriteConsoleW

    ; Clean up space allocated on stack
    add  rsp, 264

    ret
MyFunction ENDP

相当于下面的C代码:

void MyFunction()
{
   TCHAR szBuffer[100];
   DWORD dwCount;

   WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
                 L"Type some text:\n",
                 16,
                 &dwCount,
                 NULL);

   ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE),
                szBuffer,
                100,
                &dwCount,
                NULL);

   WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
                 szBuffer,
                 dwCount,
                 &dwCount,
                 NULL);
}

注意:为了清楚起见,省略了错误检查!这不是真正编写代码的好方法!


或者,您可以利用 C 标准库的强大功能来避免所有复杂的、特定于操作系统的东西,它已经为您封装了所有这些。您只需链接到适当的目标文件,然后调用类似printfscanf 的函数。有关入门的帮助,请参阅 the answers to this question

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多