【问题标题】:NASM - printf doesn't print the first characterNASM - printf 不打印第一个字符
【发布时间】:2016-11-17 21:55:18
【问题描述】:

我想写一个程序来返回你写的字符串。但它总是在没有第一个字符的情况下打印它。此外,它不会返回第一个空格之后的任何内容。

例子:

IN: test
OUT: est

代码:

extern printf, scanf, exit
global main

section .text
main:
    push rbp
                            ;input of string
    mov rdi, format
    mov rsi, string
    mov rax, 0
    call scanf

                            ;output of string
    mov rdi, format_out
    mov rsi, qword [string]
    mov rax, 0
    call printf
_exit:                        ;end of program
    pop rbp
    call exit

section .data
  format     db "%s", 0
  string     db 0
  format_out db "You wrote: %s", 0

我注意到如果我将string db 0 更改为string db",它会显示错误,但程序可以正常工作,将整个句子打印到第一个空格。不幸的是,我不知道该怎么做该信息。感谢您的回答。

【问题讨论】:

  • 我猜string 是您存储用户输入的字符串的变量。您希望用户输入多少个字符?变量string的大小是多少?
  • 嗯,我不知道。假设 20 是最大字符数。我现在该怎么办?
  • 那么你应该为字符串分配超过 1 个字节,足够你的 20 max
  • 我不知道这种语法,但为什么mov rsi, stringmov rsi, qword [string] 看起来不同?调用应该相同。
  • Zumalo,你的字符串太小了,只有一个字节。你需要像string times 21 db 0 这样的东西。

标签: assembly printf nasm x86-64


【解决方案1】:

printf("%s", ...) 接受一个指针 arg,但您将字符串内容的前 8 个字节传递给它。使用 mov rsi, string 获取 mov-immediate 而不是 mov rsi, [string](这是一个负载)。

(或者为了节省 2 个代码字节,mov esi, string,因为在默认代码模型中,静态地址保证适合 32 位。)


正如 cmets 中所指出的,您的静态缓冲区太小了。由于您的格式字符串没有大小限制,因此您需要一个无限大小的缓冲区来避免长输入行溢出它的风险。

但是让我们假设 1024B 缓冲区足够安全。或者更好的是,使用%1023s,这样就可以保证足够了。我们不希望可执行文件中有 1024B 个零;那太傻了。所以我们应该在 BSS 中保留 1024B:

section .rodata
  format:     db "%1023s", 0         # actually set a size limit, leaving room for the \0
  format_out: db "You wrote: %s", 0

section .bss
  string:     resb 1024              # RESERVE 1024 bytes.  Only works in .bss

没有理由在数据的标签名称后省略:,以及good reason not to

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-17
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    • 1970-01-01
    • 1970-01-01
    • 2015-04-25
    相关资源
    最近更新 更多