【问题标题】:Linux Assembly - Printing unicode without printfLinux 程序集 - 不使用 printf 打印 unicode
【发布时间】:2020-09-29 21:28:30
【问题描述】:

有没有办法在不使用 printf 的情况下将 unicode 字符打印到 Linux 控制台?

我知道 printf 是“正确”的方法,我只是想知道它是否可以使用纯 x86 程序集。

【问题讨论】:

  • printf 或 unicode 没有什么神奇之处。您可以直接使用write,或者直接使用libc 包装器或系统调用。只要您实际使用正确的 unicode 值并且您的终端(或输出 fd 另一端的其他任何东西)都能理解它。
  • 控制台只是一个文件。您只需以任何您想要的方式发送字符(普通、unicode、控制字符)。我怀疑你对接收部分(打印/显示)更感兴趣,但这也更复杂,它取决于控制台/打印机(所以关于 Linux 的不多,控制台可以显示在其他操作系统上)。

标签: linux assembly unicode x86 system-calls


【解决方案1】:

如果使用纯 x86 程序集,您的意思是不必包含/链接任何第 3 方库,那么可以,您可以使用内核服务 write 打印到控制台。我不认为它比使用 C 库更不正确。我将以下以 UTF-8 编码的示例保存为“sample.asm”,然后组装、链接并运行

nasm -f ELF32 sample.asm -o sample.o
ld sample.o -o sample -m elf_i386
./sample

它按预期工作。

SEGMENT .data
Sample DB "Sample text of mixed alphabets:",10
       DB "Éireannach (Eireannach in western European alphabet)",10
       DB "Čapek (Capek in central European alphabet)",10
       DB "Ørsted (Oersted in Nordic alphabet)",10
       DB "Aukštaičių (Aukshtaiciu in Baltic alphabet)",10
       DB "Ὅμηρος (Homer in Greek alphabet)",10
       DB "Yumuşak ğ (Yumushak g in Turkish aplhabet)",10
       DB "Maðkur (Mathkur in Icelandic alphabet)",10
       DB "דגבא (ABGD in Hebrew alphabet)",10
       DB "Достоевский (Dostoevsky in Cyrillic alphabet)",10
       DB 0
SizeOfSample EQU $ - Sample
SEGMENT .text
GLOBAL _start:
_start:MOV EAX,4      ; Kernel function sys_write in 32bit mode.
       MOV EBX,1      ; File descriptor of standard output.
       MOV ECX,Sample ; Offset of the written text.
       MOV EDX,SizeOfSample ; Number of bytes (not characters).
       INT 0x80       ; Invoke kernel service.
       MOV EAX,1      ; Kernel function sys_exit in 32bit mode.
       INT 0x80       ; Invoke kernel service.

以下是 64 位模式下的相同示例:

SEGMENT .data
Sample DB "Sample text of mixed alphabets:",10
       DB "Éireannach (Eireannach in western European alphabet)",10
       DB "Čapek (Capek in central European alphabet)",10
       DB "Ørsted (Oersted in Nordic alphabet)",10
       DB "Aukštaičių (Aukshtaiciu in Baltic alphabet)",10
       DB "Ὅμηρος (Homer in Greek alphabet)",10
       DB "Yumuşak ğ (Yumushak g in Turkish aplhabet)",10
       DB "Maðkur (Mathkur in Icelandic alphabet)",10
       DB "דגבא (ABGD in Hebrew alphabet)",10
       DB "Достоевский (Dostoevsky in Cyrillic alphabet)",10
       DB 0
SizeOfSample EQU $ - Sample
SEGMENT .text
GLOBAL _start:
_start:MOV RAX,1        ; Kernel function sys_write in 64bit mode.
       MOV RDI,1        ; File descriptor of standard output.
       LEA RSI,[Sample] ; Offset of the written text.
       MOV RDX,SizeOfSample ; Number of bytes (not characters).
       SYSCALL          ; Invoke kernel service.
       MOV EAX,60       ; Kernel function sys_exit in 64bit mode.
       SYSCALL          ; Invoke kernel service.

创建于

nasm -f ELF64 sample.asm -o sample.o
ld sample.o -o sample 
./sample

【讨论】:

  • 您不必要地将二进制 0 字节写入标准输出。这通常不是一件好事,尽管如果 stdout 是一个终端,大多数终端仿真器都会忽略它。 (write 采用 void*size_t len,而不是以 0 结尾的 C 字符串)
猜你喜欢
  • 2012-01-21
  • 2014-07-28
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 2015-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多