I'm writing simple clock program with NASM. I'm using Ubuntu 14.10 Vagrant box under OSX via iTerm. Terminal is xterm, so should be VT-100 compatible.
我正在用NASM编写简单的时钟程序。我通过iTerm在OSX下使用Ubuntu 14.10 Vagrant box。终端是xterm,因此应该兼容VT-100。
I need to remove one line. For instance, I expect the following behaviour:
我需要删除一行。例如,我期望以下行为:
Hello, this is clock program
13:01:25 UTC+4
Next moment:
Hello, this is clock program
13:01:26 UTC+4
I wrote the following functions. For print:
我写了以下函数。用于打印:
func_print:
mov eax, sys_write
mov ebx, stdout
int 0x80
ret
For clear:
clr db 0x1b, "[K"
clr_len equ $-clr
...
func_clear:
mov ecx, clr
mov edx, clr_len
call func_print
For saving and restoring positions I use VT-100 and its commands: [7
and [8
respectively:
为了保存和恢复位置,我使用VT-100及其命令:[7和[8]:
csave db 0x1b, "[7"
csave_len equ $-csave
crestore db 0x1b, "[8"
crestore_len equ $-crestore
My code:
global _start
_start:
mov ecx, welcome
mov edx, welcome_len
call func_print
call func_print
call func_save_cursor_pos
mov dword [tv_sec], 2
mov dword [tv_usec], 0
call func_sleep
call func_clear
call func_restore_cursor_pos
mov ecx, welcome
mov edx, welcome_len
call func_print
jmp func_exit
However, the result is:
但结果是:
vagrant@vagrant-ubuntu-trusty-64:~$ ./run.sh
Hello, this is the clock program
Hello, this is the clock program
Hello, this is the clock program
vagrant@vagrant-ubuntu-trusty-64:~$
If I change clr
by adding [1A
or [1B
it seems to be removing lines to much higher than needed or lower:
如果我通过添加[1A或[1B]来改变clr,它似乎是将线条移除到远高于所需要的值或更低:
vagrant@vagrant-ubuntu-trusty-64:~$ ./run.sh
Hello, this is the clock program
Hello, this is the clock program
Hello, this is the clock program
vagrant@vagrant-ubuntu-trusty-64:~$
How can I fix it? What is the correct code?
我该如何解决?什么是正确的代码?
1 个解决方案
#1
I suspect that your issue is related to the newline implied to be in welcome db "Hello, this is the clock program", 10
. I can't tell for sure because you didn't post that part of your code.
我怀疑你的问题与欢迎db中暗示的新行有关“你好,这是时钟程序”,10。我无法确定,因为你没有发布你的代码部分。
I think that this causes an issue because the newline causes the terminal to scroll - when I removed the newline from my version, it worked properly. If you only need to update one line, it works to just not have a newline.
我认为这会导致一个问题,因为换行导致终端滚动 - 当我从我的版本中删除换行符时,它正常工作。如果您只需要更新一行,它就可以没有换行符。
I suspect that the save and restore operations work on literal physical locations on the screen - not logical locations that get scrolled by newlines.
我怀疑保存和恢复操作在屏幕上的文字物理位置上工作 - 而不是由换行符滚动的逻辑位置。
In general, however, I'd recommend using the cursor manipulation escape codes instead:
但是,一般情况下,我建议使用光标操作转义码:
- When you're ready to redraw your output, write
db 0x1b, "[nA"
to move up n lines. (You'll need to put the number in there.) - Immediately after that (or after any subsequent newline), write
db 0x1b, "[K"
to clear that line. (You already knew this, but I'm including it for completeness.)
当您准备重绘输出时,请写入db 0x1b,“[nA”向上移动n行。 (你需要把号码放在那里。)
紧接着(或任何后续换行符之后),写入db 0x1b,“[K”清除该行。 (你已经知道了这一点,但我将其包括在内是为了完整性。)
I wrote an example program to implement this, based partially on yours. It displays:
我写了一个示例程序来实现它,部分基于你的。它显示:
Hello, this is the clock program.
Line two.
Then, a short while later
不久之后
=== TEST ===
More.
And then
=== TEST 2 ===
Again.
This technique should be generalizable to any reasonable number of lines.
该技术应该可以推广到任何合理数量的线。
BITS 32
section .text
welcome db "Hello, this is the clock program", 10, "Line two.", 10
welcome_len equ $-welcome
test_str db 0x1b, "[2A", 0x1b, "[K=== TEST ===", 10, 0x1b, "[KMore.", 10
test_len equ $-test_str
test2_str db 0x1b, "[2A", 0x1b, "[K=== TEST 2 ===", 10, 0x1b, "[KAgain.", 10
test2_len equ $-test2_str
func_print:
mov eax, 4
mov ebx, 1
int 0x80
ret
pause: ; Note: DON'T EVER USE THIS IN A REAL PROGRAM. This is not how you sleep properly.
mov eax, 0
loop:
inc eax
cmp eax, 1000000000
jl loop
ret
global _start
_start:
mov ecx, welcome
mov edx, welcome_len
call func_print
call pause
mov ecx, test_str
mov edx, test_len
call func_print
call pause
mov ecx, test2_str
mov edx, test2_len
call func_print
mov eax, 1
mov ebx, 0
int 0x80
#1
I suspect that your issue is related to the newline implied to be in welcome db "Hello, this is the clock program", 10
. I can't tell for sure because you didn't post that part of your code.
我怀疑你的问题与欢迎db中暗示的新行有关“你好,这是时钟程序”,10。我无法确定,因为你没有发布你的代码部分。
I think that this causes an issue because the newline causes the terminal to scroll - when I removed the newline from my version, it worked properly. If you only need to update one line, it works to just not have a newline.
我认为这会导致一个问题,因为换行导致终端滚动 - 当我从我的版本中删除换行符时,它正常工作。如果您只需要更新一行,它就可以没有换行符。
I suspect that the save and restore operations work on literal physical locations on the screen - not logical locations that get scrolled by newlines.
我怀疑保存和恢复操作在屏幕上的文字物理位置上工作 - 而不是由换行符滚动的逻辑位置。
In general, however, I'd recommend using the cursor manipulation escape codes instead:
但是,一般情况下,我建议使用光标操作转义码:
- When you're ready to redraw your output, write
db 0x1b, "[nA"
to move up n lines. (You'll need to put the number in there.) - Immediately after that (or after any subsequent newline), write
db 0x1b, "[K"
to clear that line. (You already knew this, but I'm including it for completeness.)
当您准备重绘输出时,请写入db 0x1b,“[nA”向上移动n行。 (你需要把号码放在那里。)
紧接着(或任何后续换行符之后),写入db 0x1b,“[K”清除该行。 (你已经知道了这一点,但我将其包括在内是为了完整性。)
I wrote an example program to implement this, based partially on yours. It displays:
我写了一个示例程序来实现它,部分基于你的。它显示:
Hello, this is the clock program.
Line two.
Then, a short while later
不久之后
=== TEST ===
More.
And then
=== TEST 2 ===
Again.
This technique should be generalizable to any reasonable number of lines.
该技术应该可以推广到任何合理数量的线。
BITS 32
section .text
welcome db "Hello, this is the clock program", 10, "Line two.", 10
welcome_len equ $-welcome
test_str db 0x1b, "[2A", 0x1b, "[K=== TEST ===", 10, 0x1b, "[KMore.", 10
test_len equ $-test_str
test2_str db 0x1b, "[2A", 0x1b, "[K=== TEST 2 ===", 10, 0x1b, "[KAgain.", 10
test2_len equ $-test2_str
func_print:
mov eax, 4
mov ebx, 1
int 0x80
ret
pause: ; Note: DON'T EVER USE THIS IN A REAL PROGRAM. This is not how you sleep properly.
mov eax, 0
loop:
inc eax
cmp eax, 1000000000
jl loop
ret
global _start
_start:
mov ecx, welcome
mov edx, welcome_len
call func_print
call pause
mov ecx, test_str
mov edx, test_len
call func_print
call pause
mov ecx, test2_str
mov edx, test2_len
call func_print
mov eax, 1
mov ebx, 0
int 0x80