我对组装这个东西完全陌生,在谷歌上搜索了好几个小时,在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格式,因此建议以该格式提出解决方案。
打印\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字节的返回地址。)
使用彼得·科德斯的有益指导解决了这个问题。
工作代码如下:
jmp