使用wprintf linux x86-64平台打印出汇编中的unicode字符

时间:2013-08-06 05:03:22

标签: assembly unicode nasm gas

我正在使用linux,只是尝试使用nasm和gas。我可以使用c ++

使用wprintf打印出unicode字符
#include <wchar.h>
#include <locale.h>
#include <stdio.h>
int main() 
{
  //printf("helloworld"); // can't do this AND wprintf in same program
  setlocale(LC_ALL, "");
  wprintf(L"%lc",0x307E); //prints out japanese hiragana ma ま
}
然而,我非常困惑于尝试在汇编(英特尔和气体语法)中进行。我的主要困惑是.data部分。我甚至给gcc -S开关看他们是怎么做的。它们使用13 .string语句执行格式字符串,其中许多是空字符串,每个字符位于单独的.string上。我读到你可以通过将字符串放在dw而不是db中来在nasm中将常规字符串作为一个宽字符串。所以当然我尝试使用.int作为汽油,但这并不是很好。我的意思是它打印出额外的灰色问号。 这是我目前的代码

.section .data
locale:
  .string ""
printformat:
  .int '%','l','c'
printwide:
  .int 0x307E,0
.section .text
.global _start
_start:
movq    $locale,%rsi
movq    $6,%rdi
call    setlocale
movq    $printformat,%rdi
movq    $printwide,%rsi
movq    $0,%rax
call    wprintf
movq    $2,%rdi
call    exit

这会产生5个灰色的问号,然后是平假名ま(ma)。您会认为在'%','l','c'之后应该有一个0,但是这不起作用 - 在这样做之后只输出问号。 我能够打印平假名并且没有问号的唯一方法是跳过格式字符串并将printwide加载到rdi中。

此外,目前这是出于教育目的。 所以基本上,你如何在语法和英特尔中做格式字符串?在c ++中,你只需在它前面放一个L. (是的,我想你可以将%lc更改为十六进制,但我不想这样做)

编辑这是有效的(我将$ printwide更改为printwide并将printformat更改为.strings,就像gcc -S列表那样。)但为什么它有效并且有更好的方法可以写出来除了使用这么多.string语句之外的格式?你会怎么用intel语法做的?

.section .data
locale:
    .string ""
printformat:
    .string "%"
    .string ""
    .string ""
    .string "l"
    .string ""
    .string ""
    .string "c"
    .string ""
    .string ""
    .string ""
    .string ""
    .string ""
    .string ""
printwide:
    .word 0x307E
.section .text
.global _start
_start:
movq    $locale,%rsi
movq    $6,%rdi
call    setlocale
movq    $printformat,%rdi
movq    printwide,%rsi
movq    $0,%rax
call    wprintf
movq    $2,%rdi
call    exit

1 个答案:

答案 0 :(得分:1)

我对答案感到惊讶。我猜64位宽字符是32位。我通过阅读nasm找到了这一点。您可以通过以下

在intel语法中创建字符串utf-16
printformat dw __utf16__("%lc"),0

但它只在我做的时候才有用

printformat dd __utf32__("%lc"),0

因此at&amp; t语法中的等价物将是

.long '%','l','c',0

我猜gcc -S使用如此多的字符串列表使其为32位宽

.string“%”= 16位(%和自动归零)然后另外8位用空字符串,然后另外8位用另一个空字符串。

相关问题