【问题标题】:Accepting user input in assembly? Simple program (On macOS)在汇编中接受用户输入?简单程序(在 macOS 上)
【发布时间】:2017-12-19 15:15:00
【问题描述】:

我在这个简单的程序中遇到了一些问题,它接受用户的名字并打印“你好,这里的名字”

这是我目前的代码...

%define SYSCALL_WRITE 0x2000004
%define SYSCALL_EXIT  0x2000001
%define SYSCALL_READ  0x2000003

SECTION .data
  prompt db "Enter name "
  text2 db "Hello, "

SECTION .bss
  name resb 16

SECTION .text
  global _start

_start:
  call _printText1
  call _getInput
  call _printText2
  call _printName
  mov rax, SYSCALL_EXIT
  mov rdi, 0
  syscall

_printText1:
  mov rax, SYSCALL_WRITE
  mov rdi, 1
  mov rsi, prompt
  mov rdx, 11
  syscall
  ret

_getInput:
  mov rax, SYSCALL_READ
  mov rdi, 0
  mov rsi, name
  mov rdx, 1
  syscall
  ret

_printText2:
  mov rax, SYSCALL_WRITE
  mov rdi, 1
  mov rsi, text2
  mov rdx, 7  
  syscall
  ret

_printName:
  mov rax, SYSCALL_WRITE
  mov rdi, 1
  mov rsi, name
  mov rdx, 16
  syscall
  ret

当我执行它时,输出不会打印“Hello,”。输入名称的第一个字母在下一个命令行之前打印...

nMy-MacBook:Assembly username$ ame

名称的其余部分被接受为命令参数,系统对此进行回复

-bash: ame: command not found

我到底做错了什么?我删除了 _getInput 和 _printName 函数,它仍然只打印“Enter name”而不打印“Hello,”。

谢谢。

【问题讨论】:

  • 你在使用调试器吗?
  • @InfinitelyManic 我只是在我的 Mac 上使用终端。
  • 是的 - 但您是否真的在使用一些调试器软件在汇编代码执行时单步执行它?使用调试器可帮助您识别故障点。比如我用GDB;但是,我从命令行使用 Linux 操作系统或 OpenBSD。
  • @InfinitelyManic 不,我没有使用调试器。出于某种原因,我只是假设不会有一个组装。我一定会研究 Mac 的调试器。
  • 我刚刚复制了你的代码;但在 Linux 操作系统中;其中(如果您不知道的话)使用相同的 64 位系统 ABI,因此它通常可以与系统调用编号等一些调整一起使用。您的 _getInput 系统调用仅接受一 (1) 个字节。从那个开始......

标签: assembly nasm x86-64 mach-o


【解决方案1】:

在汇编中,您必须考虑到每一点;尤其是在做输入输出的时候。

以下是您对 RDX 进行编辑的部分代码,其中我选择了一些任意长度。

最后一行显示命令行程序执行、提示、用户输入,然后是最终输出。

; reference:
; https://stackoverflow.com/questions/47889972/accepting-user-input-in-assembly-simple-program-on-macos

; lsb_release -a
; Distributor ID: Ubuntu
; Description:    Ubuntu 16.04.3 LTS
; Release:        16.04
; Codename:       xenial

; assemble and link
; nasm -f elf64 -g -F dwarf srsrso_001.s -o srsrso_001.o  && ld srsrso_001.o -o srsrso_001

;%define SYSCALL_WRITE 0x2000004
;%define SYSCALL_EXIT  0x2000001
;%define SYSCALL_READ  0x2000003

SECTION .data
  prompt db "Enter name "
  text2 db "Hello, ",0xa,0

        SYSCALL_WRITE equ       1
        SYSCALL_EXIT  equ       60
        SYSCALL_READ  equ       0

SECTION .bss
  name resb 0xff                ; some length

SECTION .text
  global _start

_start:
 call _printText1
 call _getInput
 call _printText2
 call _printName

  mov rax, 60
  mov rdi, 0
  syscall

_printText1:
  mov rax, SYSCALL_WRITE
  mov rdi, 1
  mov rsi, prompt
  mov rdx, 11
  syscall
  ret

_getInput:
  mov rax, SYSCALL_READ
  mov rdi, 0
  mov rsi, name
  mov rdx, 0xff ; some length
  syscall
  ret

_printText2:
  mov rax, SYSCALL_WRITE
  mov rdi, 1
  mov rsi, text2
  mov rdx, 7
  syscall
  ret

_printName:
  mov rax, SYSCALL_WRITE
  mov rdi, 1
  mov rsi, name
  mov rdx, 0xff ; some length
  syscall
  ret

示例输出:

$ ./srsrso_001
Enter name David John Lewis Benjamen Kyle Smith-Wenson
Hello, David John Lewis Benjamen Kyle Smith-Wenson

【讨论】:

  • 赞成显示示例输入/输出,但后来我意识到您要求输入 65535 字节长,但您没有显示输入缓冲区调整大小,即原始 name resb 16 这是另一个错误,超过 16 个字符的输入现在可能会使应用程序崩溃。就像您自己写的那样:“在汇编中,您必须考虑每一位”,这包括存储空间。请修复。 (通常包含构建步骤也很好,但这更像是问题,而不是答案,但随机阅读器更容易重现结果。
  • +Peg7g - 希望我的更改有所帮助。谢谢。
  • 它就像魅力一样。这就是我在我的 macbook 2019 上尝试的方式:nasm -fmacho64 input.asm && clang -Wl,-no_pie input.o && ./a.out
猜你喜欢
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-25
  • 1970-01-01
  • 1970-01-01
  • 2015-10-28
相关资源
最近更新 更多