VT-100 命令运行异常
VT-100 commands are working strangely
我正在用 NASM 编写简单的时钟程序。我通过 iTerm 在 OSX 下使用 Ubuntu 14.10 Vagrant box。终端是 xterm,因此应该与 VT-100 兼容。
我需要删除一行。例如,我期望以下行为:
Hello, this is clock program
13:01:25 UTC+4
下一刻:
Hello, this is clock program
13:01:26 UTC+4
我写了下面的函数。对于打印:
func_print:
mov eax, sys_write
mov ebx, stdout
int 0x80
ret
清除:
clr db 0x1b, "[K"
clr_len equ $-clr
...
func_clear:
mov ecx, clr
mov edx, clr_len
call func_print
为了保存和恢复位置,我使用 VT-100 及其命令:分别为 [7
和 [8
:
csave db 0x1b, "[7"
csave_len equ $-csave
crestore db 0x1b, "[8"
crestore_len equ $-crestore
我的代码:
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
然而,结果是:
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:~$
如果我通过添加 [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:~$
我该如何解决?正确的代码是什么?
我怀疑您的问题与隐含在 welcome db "Hello, this is the clock program", 10
中的换行符有关。我不能肯定,因为你没有 post 你的那部分代码。
我认为这会导致问题,因为换行符会导致终端滚动 - 当我从我的版本中删除换行符时,它可以正常工作。如果您只需要更新一行,则可以不使用换行符。
我怀疑保存和恢复操作在屏幕上的实际物理位置上起作用——而不是按换行符滚动的逻辑位置。
不过,一般来说,我建议改用游标操作转义码:
- 当您准备好重绘输出时,写入
db 0x1b, "[nA"
以向上移动 n 行。 (你需要把号码放在那里。)
- 在那之后(或任何后续换行之后),立即写入
db 0x1b, "[K"
以清除该行。 (您已经知道这一点,但为了完整起见,我将其包括在内。)
我写了一个示例程序来实现这个,部分基于你的。它显示:
Hello, this is the clock program.
Line two.
然后,不久之后
=== TEST ===
More.
然后
=== TEST 2 ===
Again.
此技术应该可以推广到任何合理数量的行。
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
我正在用 NASM 编写简单的时钟程序。我通过 iTerm 在 OSX 下使用 Ubuntu 14.10 Vagrant box。终端是 xterm,因此应该与 VT-100 兼容。
我需要删除一行。例如,我期望以下行为:
Hello, this is clock program
13:01:25 UTC+4
下一刻:
Hello, this is clock program
13:01:26 UTC+4
我写了下面的函数。对于打印:
func_print:
mov eax, sys_write
mov ebx, stdout
int 0x80
ret
清除:
clr db 0x1b, "[K"
clr_len equ $-clr
...
func_clear:
mov ecx, clr
mov edx, clr_len
call func_print
为了保存和恢复位置,我使用 VT-100 及其命令:分别为 [7
和 [8
:
csave db 0x1b, "[7"
csave_len equ $-csave
crestore db 0x1b, "[8"
crestore_len equ $-crestore
我的代码:
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
然而,结果是:
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:~$
如果我通过添加 [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:~$
我该如何解决?正确的代码是什么?
我怀疑您的问题与隐含在 welcome db "Hello, this is the clock program", 10
中的换行符有关。我不能肯定,因为你没有 post 你的那部分代码。
我认为这会导致问题,因为换行符会导致终端滚动 - 当我从我的版本中删除换行符时,它可以正常工作。如果您只需要更新一行,则可以不使用换行符。
我怀疑保存和恢复操作在屏幕上的实际物理位置上起作用——而不是按换行符滚动的逻辑位置。
不过,一般来说,我建议改用游标操作转义码:
- 当您准备好重绘输出时,写入
db 0x1b, "[nA"
以向上移动 n 行。 (你需要把号码放在那里。) - 在那之后(或任何后续换行之后),立即写入
db 0x1b, "[K"
以清除该行。 (您已经知道这一点,但为了完整起见,我将其包括在内。)
我写了一个示例程序来实现这个,部分基于你的。它显示:
Hello, this is the clock program.
Line two.
然后,不久之后
=== TEST ===
More.
然后
=== TEST 2 ===
Again.
此技术应该可以推广到任何合理数量的行。
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