Tips その3


JISコードをShift-JISコードに変換するには

本来ならJISとShift-JISの約束をコードにすると、次のようになります。JISもSJISも2Byteコードなので、引数も戻り値も1文字分のWord(2Byte)です。

function JisToSJis(jis: Word): Word;
var
  hib, lob: Word;
begin
  hib:= (jis shr 8) and $FF;
  lob:= jis and $FF;
  if Boolean(hib and 1) then
    lob:= lob + $1F
  else
    lob:= lob + $7D;
  if lob >= $7F then Inc(lob);
    hib:= ((hib - $21) shr 1) + $81;
    if hib > $9F then hib:= hib + $40;
  Result:= (hib shl 8) or lob;
end;

インラインアセンブラで書くと次の通り。

function JisToSJis(jis: Word): Word; assembler;
asm
  add ax,0a17eh ; shr ah,1 ; jb @1
  cmp al,0deh ; sbb al,5eh
  @1: xor ah,0e0h
end;

後者の方が若干高速なのかしら。大して違わないか。


Shift-JISコードをJISコードに変換するには

上の逆の処理ですな。

function SJisToJis(sjis: Word): Word;
var
  hib, lob: Byte;
begin
  hib:= (sjis shr 8) and $FF;
  lob:= sjis and $FF;
  if hib <= $9F then
    hib:= hib - $71
  else
    hib:= hib - $B1;
  hib:= (hib shl 1) + 1;
  if lob > $7F then Dec(lob);
  if lob >= $9E then
  begin
    lob:= lob - $7D;
    Inc(hib);
  end else
    lob:= lob - $1F;

  Result:= (hib shl 8) or lob;
end;

で、下がそのアセンブラ版。

function SJisToJis(sjis: Word): Word; assembler;
asm
  shl ah,1 ; sub al,1fh ; js @1
  cmp al,61h ; adc al,0deh
  @1: add ax,1fa1h ; and ax,7f7fh
end;

 


Shift-JISコードをEUCコードに変換するには

若干面倒ですが、次のようにすればいけると思います。

function SJisToEuc(sjis: Word): Word;
var
  hib, lob: Byte;
begin

  hib:= (sjis shr 8) and $ff;
  lob:= sjis and $ff;
  if hib <= $9f then
    hib:= hib - $71
  else
    hib:= hib - $b1;
  hib:= (hib shl 1) + 1;
  if lob >= $9e then
  begin
    lob := lob - $7e;
    Inc(hib);
  end else
  if lob > $7f then
    lob := lob - $20
  else
    lob := lob - $1f;

  hib:= hib or $80;
  lob:= lob or $80;
  Result:= (hib shl 8) or lob;

end;

実は、EUCコードというのは、JISコードと8080hとの論理和をとったものになります。なので、SJisToJis の結果を使って次のように書くとスッキリします。

function SJisToEuc(sjis: Word): Word;
begin
  Result:= SJisToJis(sjis) or $8080;
end;

 


EUCコードをShift-JISコードに変換するには

とりあえず、まともにやると次の通りです。

function HankToZenk(wrd: Word): Word;
const
  z : Array [1..64] of Word
      = ($2121,$2123,$2156,$2157,$2122,$2126,$2572,$2521,
         $2523,$2525,$2527,$2529,$2563,$2565,$2567,$2543,
         $213c,$2522,$2524,$2526,$2528,$252a,$252b,$252d,
         $252f,$2531,$2533,$2535,$2537,$2539,$253b,$253d,
         $253f,$2541,$2544,$2546,$2548,$254a,$254b,$254c,
         $254d,$254e,$254f,$2552,$2555,$2558,$255b,$255e,
         $255f,$2560,$2561,$2562,$2564,$2566,$2568,$2569,
         $256a,$256b,$256c,$256d,$256f,$2573,$212b,$212c);
begin
  if (wrd < $A0) or (wrd > $DF) then
    Result:= 0
  else
    Result:= z[wrd - $A0];
end;

function EucToSJis(euc: Word): Word;
var
  jis: Word;
  hib, lob: Byte;
begin
  if (euc and $ff00) = $8e00 then
    jis:= HankToZenk(euc and $ff)
  else
    jis:= euc and (not $8080);

  hib:= (jis shr 8) and $ff;
  lob:= jis and $ff;
  if (hib and 1) <> 0 then
    lob:= lob + $1f
  else
    lob:= lob + $7d;

  if lob >= $7f then Inc(lob);

  hib:= ((hib - $21) shr 1) + $81;

  if hib > $9f then hib:= hib + $40;

  Result:= (hib shl 8) or lob;

end;

HankToZenk というのは半角カナを全角カナに変換する関数です。

で、EUCコードと7F7Fhとの論理積はJISコードになるので、JisToSJis を使えば次のように簡略することもできます。

function EUCToSJis(euc: Word): Word;
begin
  Result:= JisToSJis(euc and $7F7F);
end;

びゅーちふる。


JISコードをEUCコードに変換するには

Windowsではあまり使わないと思うんですが、とりあえず次の通りです。JISコードと8080hとの論理和をとれば、それがEUCコードです。

function JisToEuc(jis: Word): Word;
begin
  Result:= jis or $8080;
end;

アセンブラで決めたければ次の通り。

function JisToEuc(jis: Word): Word;
asm
  or ax,8080h
end;

 


EUCコードをJISコードに変換するには

EUCコードと7F7Fhとの論理積がJISコードです。なので、次の通り。

function EucToJis(euc: Word): Word;
begin
  Result:= euc and $7F7F;
end;

そのアセンブラ版。

function EucToJis(euc: Word): Word;
asm
  and ax,7F7Fh
end;

 


EBCDICコードをASCIIコードに変換するには

EBCDICとASCIIの間には変換の法則性はありません。ですので、テーブルをゴリゴリ作って、それで対照して戻してやるしかないです。やるとすれば次のような感じになります。

const
  { EBCDIC→ASCII変換用テーブル }
  tblEToA: Array [0..255] of Byte =
    ($00, $01, $02, $03, $9c, $09, $86, $7f, //00-07
     $97, $8d, $8e, $0b, $0c, $0d, $0e, $0f, //08-0F
     $10, $11, $12, $13, $9d, $85, $08, $87, //10-17
     $18, $19, $92, $8f, $1c, $1d, $1e, $1f, //18-1F
     $80, $81, $82, $83, $84, $0a, $17, $1b, //20-27
     $88, $89, $8a, $8b, $8c, $05, $06, $07, //28-2F
     $90, $91, $16, $93, $94, $95, $96, $04, //30-37
     $98, $99, $9a, $9b, $14, $15, $9e, $1a, //38-3F
     $20, $a0, $a1, $a2, $a3, $a4, $a5, $a6, //40-47
     $a7, $a8, $5b, $2e, $3c, $28, $2b, $21, //48-4F
     $26, $a9, $aa, $ab, $ac, $ad, $ae, $af, //50-57
     $b0, $b1, $5d, $24, $2a, $29, $3b, $5e, //58-5F
     $2d, $2f, $b2, $b3, $b4, $b5, $b6, $b7, //60-6F
     $b8, $b9, $7c, $2c, $25, $5f, $3e, $3f, //68-6F
     $ba, $bb, $bc, $bd, $be, $bf, $c0, $c1, //70-77
     $c2, $60, $3a, $23, $40, $27, $3d, $22, //78-7F
     $c3, $61, $62, $63, $64, $65, $66, $67, //80-87
     $68, $69, $c4, $c5, $c6, $c7, $c8, $c9, //88-8F
     $ca, $6a, $6b, $6c, $6d, $6e, $6f, $70, //90-97
     $71, $72, $cb, $cc, $cd, $ce, $cf, $d0, //98-9F
     $d1, $7e, $73, $74, $75, $76, $77, $78, //A0-A7
     $79, $7a, $d2, $d3, $d4, $d5, $d6, $d7, //A8-AF
     $d8, $d9, $da, $db, $dc, $dd, $de, $df, //B0-B7
     $e0, $e1, $e2, $e3, $e4, $e5, $e6, $e7, //B8-BF
     $7b, $41, $42, $43, $44, $45, $46, $47, //C0-C7
     $48, $49, $e8, $e9, $ea, $eb, $ec, $ed, //C8-CF
     $7d, $4a, $4b, $4c, $4d, $4e, $4f, $50, //D0-D7
     $51, $52, $ee, $ef, $f0, $f1, $f2, $f3, //D8-DF
     $5c, $9f, $53, $54, $55, $56, $57, $58, //E0-E7
     $59, $5a, $f4, $f5, $f6, $f7, $f8, $f9, //E8-EF
     $30, $31, $32, $33, $34, $35, $36, $37, //F0-F7
     $38, $39, $fa, $fb, $fc, $fd, $fe, $ff);//F8-FF

function EbcdicToAscii(e: Char): Char;
begin
  Result:= Chr(tblEToA[Ord(e)]);
end;

EBCDICの仕様はNEC系とか日立系などベンダーによって微妙に変更されていたりするので、上のテーブルもそれにあわせてカスタマイズが必要になるかもしれません。この例のテーブルは一般的なものです。


ASCIIコードをEBCDICコードに変換するには

ASCIIとEBCDICの間には変換の法則はないので、やはりテーブルを作るしかないです。

const
 
{ ASCII→EBCDIC(K)変換用テーブル }
  tblAToE: Array [0..255] of Byte =
    ($00, $01, $02, $03, $37, $2d, $2e, $2f, //00-07
     $16, $05, $25, $0b, $0c, $0d, $0e, $0f, //08-0F
     $10, $11, $12, $13, $3c, $3d, $32, $26, //10-17
     $18, $19, $3f, $27, $1c, $1d, $1e, $1f, //18-1F
     $40, $4f, $7f, $7b, $5b, $6c, $50, $7d, //20-27
     $4d, $5d, $5c, $4e, $6b, $60, $4b, $61, //28-2F
     $f0, $f1, $f2, $f3, $f4, $f5, $f6, $f7, //30-37
     $f8, $f9, $7a, $5e, $4c, $7e, $6e, $6f, //38-3F
     $7c, $c1, $c2, $c3, $c4, $c5, $c6, $c7, //40-47
     $c8, $c9, $d1, $d2, $d3, $d4, $d5, $d6, //48-4F
     $d7, $d8, $d9, $e2, $e3, $e4, $e5, $e6, //50-57
     $e7, $e8, $e9, $4a, $e0, $5a, $5f, $6d, //58-5F
     $79, $81, $82, $83, $84, $85, $86, $87, //60-67
     $88, $89, $91, $92, $93, $94, $95, $96, //68-6F
     $97, $98, $99, $a2, $a3, $a4, $a5, $a6, //70-77
     $a7, $a8, $a9, $c0, $6a, $d0, $a1, $07, //78-7F
     $20, $21, $22, $23, $24, $15, $06, $17, //80-87
     $28, $29, $2a, $2b, $2c, $09, $0a, $1b, //88-8F
     $30, $31, $1a, $33, $34, $35, $36, $08, //90-97
     $38, $39, $3a, $3b, $04, $14, $3e, $e1, //98-9F
     $41, $42, $43, $44, $45, $46, $47, $48, //A0-A7
     $49, $51, $52, $53, $54, $55, $56, $57, //A8-AF
     $58, $59, $62, $63, $64, $65, $66, $67, //B0-B7
     $68, $69, $70, $71, $72, $73, $74, $75, //B8-BF
     $76, $77, $78, $80, $8a, $8b, $8c, $8d, //C0-C7
     $8e, $8f, $90, $9a, $9b, $9c, $9d, $9e, //C8-CF
     $9f, $a0, $aa, $ab, $ac, $ad, $ae, $af, //D0-D7
     $b0, $b1, $b2, $b3, $b4, $b5, $b6, $b7, //D8-DF
     $b8, $b9, $ba, $bb, $bc, $bd, $be, $bf, //E0-E7
     $ca, $cb, $cc, $cd, $ce, $cf, $da, $db, //E8-EF
     $dc, $dd, $de, $df, $ea, $eb, $ec, $ed, //F0-F7
     $ee, $ef, $fa, $fb, $fc, $fd, $fe, $ff);//F8-FF

function AsciiToEbcdic(a: Char): Char;
begin
  Result:= Chr(tblAToE[Ord(a)]);
end;

力技ですな。


[ Delphi へ戻る ]