更新已在NASM中每秒打印的字符串

问题描述 投票:0回答:2

我对组装这个东西完全陌生,在谷歌上搜索了好几个小时,在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
2个回答
0
投票

打印\r回车符(ASCII代码13)以将光标置于行的开头\n换行符(ASCII 10)的方式滚动终端。

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

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

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

[注意,在数据中不需要, 0,因为您要将这些缓冲区传递给write而不是printf,因此它们不必是0终止的隐含长度C字符串。您也不需要对mov rdx, 6进行硬编码,可以将mov rdx, hello_len与汇编程序一起使用为您计算代码。


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


对于循环,请不要使用nanosleep;使用call _start。您不想发送寄信人地址;最终将导致堆栈溢出(大约一百万秒后:8MiB堆栈大小限制,并调用推送了一个8字节的返回地址。)


0
投票

使用彼得·科德斯的有益指导解决了这个问题。

工作代码如下:

jmp
© www.soinside.com 2019 - 2024. All rights reserved.