【问题标题】:Update the string that has already been printed every second in NASM在 NASM 中每秒更新已经打印的字符串
【发布时间】:2019-12-25 21:33:43
【问题描述】:

我对组装的东西完全陌生,谷歌搜索了几个小时,搜索 SO 并没有把事情弄清楚,所以我来这里问。

我想要达到的目标:

[first second]: hello (stays on the screen for 1 second)

[second second]: world (hello disappeared and now we have `world` in place of it)

而且这个流程是无限循环的

换句话说,我希望我的终端的标准输出在 hello 和 world 之间闪烁(更改),而无需添加任何换行符、编写字符串或任何其他内容,我只想将现有的、已打印的文本替换为其他文本。

我已经编写了无限循环,它将打印hello,然后等待一秒钟,然后打印world,然后等待一秒钟。我也把这段代码无限循环了。

这是我目前拥有的代码:

section .data
    hello db "hello",10,0
    world db "world",10,0
    delay dq 1,0

section .text
    global _start

_start:
    mov rax, 1
    mov rdi, 1
    mov rsi, hello
    mov rdx, 6
    syscall

    mov rax, 35
    mov rdi, delay
    mov rsi, 0
    syscall

    mov rax, 1
    mov rdi, 1
    mov rsi, world
    mov rdx, 6
    syscall

    mov rax, 35
    mov rdi, delay
    mov rsi, 0
    syscall

    call _start

请注意,我使用 elf64 asm 格式,非常感谢您提出该格式的解决方案。

【问题讨论】:

    标签: linux assembly nasm system-calls


    【解决方案1】:

    打印\r 回车符(ASCII 码 13)将光标放在行首 不会像\n 换行符(ASCII 码 10)那样滚动终端。

    然后你可以覆盖你最后写的东西。如果它更短,您可以在可见字符之后打印空格以“擦除”仍然存在的后面的字符。

    例如因为这两个词的长度相同,你可以这样做:

    section .rodata
        hello db 13, "hello"        ; `\rhello`
        hello_len equ $ - hello
        world db 13, "world"
        world_len equ $ - world
    

    请注意,您的数据中不需要, 0,因为您将这些缓冲区传递给write 而不是printf,因此它们不需要以0 结尾的隐式长度C 字符串。您也不需要硬编码mov rdx, 6,您可以使用mov rdx, hello_len 和汇编程序为您计算。


    对于睡眠部分,您可以使用sleep libc 函数,但对于原始系统调用,您必须使用nanosleep。 (就像你已经在做的那样。)


    对于循环,不要使用call _start;使用jmp。您不想推送退货地址;最终会堆栈溢出(大约 100 万秒后:8MiB 堆栈大小限制并调用推送 8 字节返回地址。)

    【讨论】:

    • mov rax, 1 mov rdi, 1 mov rsi, 13h mov rdx, 6 syscall 使用它并没有将光标放在行首。我也尝试使用 glibc printf 函数,但在链接阶段出错。
    • @Andrewf0s3Kosenko:write 在 RSI 中采用 指针,而不是单个字符值。此外,ASCII CR 是 13 (0x0d) 而不是 13h。用一个例子更新了我的答案。
    【解决方案2】:

    使用 Peter Cordes 的有用指导解决了这个问题。

    工作代码如下所示:

    section .data
        hello db "hello",13,0
        world db "world",13,0
        delay dq 1,0
    
    section .text
        global _start
    
    _start:
        mov rax, 1
        mov rdi, 1
        mov rsi, hello
        mov rdx, 6
        syscall
    
        mov rax, 35
        mov rdi, delay
        mov rsi, 0
        syscall
    
        mov rax, 1
        mov rdi, 1
        mov rsi, world
        mov rdx, 6
        syscall
    
        mov rax, 35
        mov rdi, delay
        mov rsi, 0
        syscall
    
        jmp _start
    

    【讨论】:

      猜你喜欢
      • 2014-12-31
      • 1970-01-01
      • 1970-01-01
      • 2017-04-01
      • 1970-01-01
      • 2017-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多