Yabu.log

ITなどの雑記

AS400やRPG言語等で利用されているEBCDICコード順ソートをJavaで実現する方法

某所でちょっと話題になったので、ASCIIのスーパーセットになっていない文字コードをソートする方法を紹介します

ASCII - Wikipedia

asciiでは文字は

  • 数字->英語大文字、英語小文字

の順で並んでいますが、最近普通に使われている文字コードも大体はASCIIコードのスーパーセットになっており、 数字と英語は同じ並びになっています。(だから日本語以外は文字化けしなかったりするケースが多いわけですね〜)

asciiが登場するより前に出現した文字コード*1この順番になっていなかったりします。

  • 英語小文字->英語大文字->数字*2

EBCDIC - Wikipedia

ラムダ式の復習なども兼ねて、こちらをJavaでソートするコードを書きました。

import java.util.*;
import java.nio.charset.*;

public class Main {
    public static void main(String[] args) throws Exception {

        //データ用意
        List<String> list = Arrays.asList("abcd","1234","ABCDEFG","Z","z");

        //ソート
        Collections.sort(list,(a,b)->{
            Charset encoding = Charset.forName("IBM1047");
            return encoding.encode(a).compareTo(encoding.encode(b));
        });

        //EBCDICでソートしたものを表示
        System.out.println(list);
        //表示結果[abcd, z, ABCDEFG, Z, 1234]
        
        //デフォルトのソート
        Collections.sort(list);
        System.out.println(list);
        //表示結果[1234, ABCDEFG, Z, abcd, z]

    }
}

Javaでサポートされている文字コードならIBM1047以外もこの方法が使えます*3

サポートされているエンコーディング

*1:EBCDIC,ASCIIどちらも1963年らしいが

*2:IBM1047の場合。オリジナルのEBCDICには英語小文字がない

*3:最近のJavaの状況を解説しているドキュメンが見つかりませんでした

「はじめて学ぶCの仕組み2」を読んだ

大体1週間程度で読み終わりました。

プログラミング学習シリーズ C言語改訂版 2 はじめて学ぶCの仕組み

プログラミング学習シリーズ C言語改訂版 2 はじめて学ぶCの仕組み

この本を読み始めた動機は

  • C言語力が低いとOSのコードを読み書きするのに障害になると感じたから
  • C++の本でC言語初心者が門前払いされていたから

C++の本を開いた理由は、大局的にはオブジェクト指向の機能がある言語でOSを読み書きしようという野望があったからです。

C++プログラミング入門

C++プログラミング入門

よかったところ

C言語から手続き型プログラミングを引いた部分を一通り学べる

などの使い方について一通り学べます。

if文やfor文とかに関する長い説明はいらないけど、 C言語の基本的な機能に自信がない・・・という私みたいな人にぴったりな本でした。

よくなかったところ

  • 演習問題があまり充実していない。
  • volatileの説明がない。まぁそもそもあまり使わないものらしいが。
  • 構造体を->で利用する方法が書かれていない

わからなかったところ

配列が持っている長さ(添え字)の情報

char s[5];この分の添え字が結局何のためにあるのかよくわかっていません。

   char s[5] = "hello";
  puts(s);

これは変数をヒープに割り当てる際に、 s[0]のアドレスから変数型*5バイト分後ろがsの領域になるように割り当てているということでしょうか。

この添え字は多分変数sの領域の確保時に、以前確保した変数と被らないように領域を確保するだけに思います。

実行時はこの配列sへの書き込み以外の方法でも書き込みに対して保護などされておらず、上書きされるように思います。

例えばsの前後に配列を確保し、アドレスがかぶるように不正なindexを設定して代入するなどして簡単にメモリ破壊ができるようです。

char a[1];
char s[6] = "hello\0";
char b[1];

puts(s); //hello

printf("a at:%p\n",a);
printf("s at:%p\n",s);
printf("b at:%p\n",b);

// a at:0x7ffee9992acf
// s at:0x7ffee9992ac9
// b at:0x7ffee9992ac8

printf("a[1] at:%p\n",&a[1]);
printf("s[1] at:%p\n",&s[1]);
printf("b[1] at:%p\n",&b[1]);

// a[1] at:0x7ffee9992ad0
// s[1] at:0x7ffee9992aca
// b[1] at:0x7ffee9992ac9

//この環境だとbはsの1バイト小さいアドレスに確保される
//b+1のアドレスはsと一致している

//注意)b[0]までが正規の範囲
//コンパイル時に警告
// test.c:32:3: warning: array index 1 is past the end of the array (which contains
//       1 element) [-Warray-bounds]
//   b[1] = 'x';
//   ^ ~
// test.c:7:3: note: array 'b' declared here
//   char b[1];
//   ^

b[1] = 'x';
//*(b+1) = 'x'; //←こんか感じでもアクセスできる

puts(s); // xello

}

変数を確保するときだけ使っているように思えます。

この本にはいわゆる「C言語は自分の足を打てる言語」的なエッセンスは書かれていません。

文字列リテラルは3つの例外を除いてポインタになっている

わからないというか、そもそもきちんと検証していなかったので検証してた。

「sizeof演算子オペランドの場合(読み替えが抑止され、配列全体のサイズが返される)」

  printf("%lu\n",sizeof "test");//5

「&演算子オペランドの場合(配列全体へのポインタが返される)」

printf("%p\n", &"test");
printf("%p\n",  "test");
//出力は同じ値になる
// 0x1052edfb3
// 0x1052edfb3

「配列初期化時の文字列リテラル(文字列リテラルは普通はcharの配列だが、この場合特別に初期化子の省略形とみなされる)」です。

char test0[5];
char test1[5] = {'t','e','s','t'};
char test2[5] = "test";

char *test3;
test3 = "test";
//宣言と代入を分けているので、静的な領域に確保した"test"という文字列のアドレスを
//格納したことになっていると思う。

printf("%p\n",test0);
printf("%p\n",test1);
printf("%p\n",test2);
printf("%p\n",test3);


//test3だけアドレスが遠い
// 0x7ffee95c8acb
// 0x7ffee95c8ac6
// 0x7ffee95c8ac1
// 0x106637fab

規格

規格と実装の差分

C11やC99があるようですが、こちらの具体的な紹介などはありませんでした。 言語としてコアな部分は変わっていないと思いますが、 本書の感想をブログに投稿中は、標準規格ではこうなっている、ということを教えてもらうことが多かったです。

ちなみに色々ネットや本を見ているとC++では結構規格が重要になってくるようです。C++11,C++14,C++17などあるようですが、

  • このバージョン以前はコードがかなり煩雑になる。
  • あるバージョンでシンプルにコードを書く方法が入ったので、時代遅れの方法を使うべきではない等。

GDBのコマンド出力をファイルに保存する方法

GDBで実行しているPGのファイルの出力は、リダイレクトなどを 使って簡単にファイルに保存することが可能です。

例えば"helloworld"をただ出力するだけのプログラム の出力結果,"helloworld"という文字列をファイルに保存するのは簡単です。

しかし、GDBのコマンド(メモリダンプなど)を行った時の出力結果を保存するのに少し手間がかかったのでここで紹介したいと思います。

GDBの出力するファイルを指定する

以下のコマンドで出力先ファイルの設定、出力開始を指定できます。

set logging file <ファイル名>
set logging on

ファイルへの出力をやめるときは以下のコマンドです

set logging off

http://www.geocities.jp/harddiskdive/gdb/gdb_13.html

ページネーションを無効化する

たくさんメモリダンプした時など、一気に出さずに 続けて出すならEnter押してね~というメッセージが出ます

--Type <return> to continue, or q <return> to quit--- / “debugging --

これはデフォルトでONになっており、邪魔ですが以下のコマンドで無効化できます。

set pagination off

https://stackoverflow.com/questions/28815621/how-to-disable-type-return-to-continue-or-q-return-to-quit-in-gdb

これは.gdbinitファイルに加えたほうがいいかもしれません。

まとめて見ると意外と簡単ですが、これを探し出すのにかなり時間がかかりました。

GDBのコマンド

GDBの動かし方について。

オンラインで試せるGDBがあったので遊び倒して見た。

GDB online Debugger | Compiler - Code, Compile, Run, Debug online C, C++

よく使う(使った)コマンドなどをまとめた。

シンボルファイル関連は後日やりたい。

コマンド 省略形 意味
set disassembly-flavor intel - アセンブラの表示をintelのものにできる
list [<行数>|<関数名>] l 関数または行数から10行周辺のソースを表示
break [<行数>|<関数名>] b 関数、または行数の位置にブレークポイントを置く
clear [<行数>|<関数名>] 関数、または行数の位置のブレークポイントを削除する
dlete bnums ... 指定されたブレークポイント番号のブレークポイントを削除する
step s シンボルファイルで紐付いたプログラムを1行実行(関数の中に入る)
stepi si 単一の機械語を一命令実行
next n シンボルファイルで紐付いたプログラムを1行実行(関数は中に入らない)
nexti ni 単一の機械語を一命令実行、サブルーチンはリターンするまで実行する
backtrace bt 関数の呼び出しトレースを表示
print <変数名> p 変数の内容を表示。&をつけてアドレスを表示したり*を付けて値参照したりできる。

メモリダンプのコマンド

  • x/<量><単位><表示形式> <アドレス>
    • 量:数字
    • 単位
      • b=1Byte
      • h=2Byte
      • w=4Byte
      • g=8Byte
    • 表示形式
      • x=符号なし16進数
      • d=符号付き10進数
      • u=符号なし10進数
      • o=符号なし8進数
      • a=絶対アドレス?
      • c=文字定数
      • f=浮動小数点(単位がw,gの時のみ有効)
      • s=文字列(null文字までを1単位とする)
      • i=機械語

起動時に -ex <ファイルまたは''囲いのコマンド>オプションをつける事で起動時にgdbにコマンドを実行させられる。

自分の場合はqemuで1234ポートでgdbサーバーを起動した後、クライアント側のgdbgdb -ex 'target remote localhost:1234'とコマンドを打つ事ですぐさまデバッグが始められる。*1

他メモ

Macではbrewで入れたGDBをそのまま動かせなかった

qiita.com

見やすいGDBのUI。良さそう

qiita.com

.gdbinitの設定方法

gdbで初期設定をAT&T記法からIntel記法に変更する方法 | サラリーマンがハッカーを真剣に目指す

*1:もちろん起動時に行いたい長ったらしい処理をファイル外だしにして引数に与えることも可能

QEMUにGDBを繋げてhariboteOSをデバッグする方法

QEMUGDBを繋げてhariboteOSを調査したいと思います。

とりあえず初期設定っぽいことはできました。

主に観測したい事

ブレイクポイントを適当に設定して以下のものを観測したい

  • IPLの動作でフロッピーの内容がメモリにロードされる様子
  • リアルモード・プロテクトモード切り替え前後
  • 画面描画直前・直後
  • 割り込みハンドラにブレイクポインタを置く(マルチタスクなどをデバッグ)

QEMU × GDBについて

https://en.wikibooks.org/wiki/QEMU/Debugging_with_QEMU

  • -S -gdb stdio:使えなかった
  • -S -gdb tcp::9000:使えた
  • -s -S:使えた

-SはデバッガのコマンドまでCPUを起動させないオプション。-s-gdb tcp::1234.の意味

z_tools/qemu/Makefilegdbを使うように-s -Sを書き足す

編集前

QEMU     = qemu-system-i386
QEMU_ARGS   = -L . -m 32 -localtime -vga std -fda fdimage0.bin -monitor stdio

default:
    $(QEMU) $(QEMU_ARGS)

編集後

QEMU     = qemu-system-i386
QEMU_ARGS   = -L . -m 32 -localtime -vga std -fda fdimage0.bin -monitor stdio -s -S
default:
    $(QEMU) $(QEMU_ARGS)

この状態でmake run. すると画面が黒い状態で止まる(-SオプションでCPUを止めているため)

別ウインドウを開き、gdb起動後にコンソールに以下を打ち込む

target remote localhost:1234

デバッガが接続される。この状況でcontinueと打ち込むと...

www.youtube.com

CPUが動きだしhariboteOSが起動する(break pointをまだ設定していないため特にデバッグっぽいことはできない)

主に観測したい事に関しては次回以降。。。

30日でできる! OS自作入門

30日でできる! OS自作入門

C言語復習ラスト。ライブラリについて

ライブラリは今までよく知らなかったので、復習ではない気がする。

ライブラリとは

このプロセスの中の .oファイルをまとめてライブラリを作ることができる

$ ar -r mylib.a a.o b.o
ar: creating archive mylib.a

$ ls -alt
-rw-r--r--   1   staff  1768  7 17 00:07 mylib.a
-rw-r--r--   1   staff   748  7 16 19:13 b.o
-rw-r--r--@  1   staff   748  7 16 19:13 a.o

$ ar -t mylib.a 
__.SYMDEF SORTED
a.o
b.o
  • 関数を使うにはプロトタイプ宣言が必要
    • #include<stdio.h>とmain関数の間にある関数の宣言のやつ
      • main関数の手前に関数を定義してしまえばプロトタイプ宣言を書かなくて良いのではないだろうか?(手抜き)
        • この方法を採用すると、呼び出し関係を把握して、関数の依存性を整理して順番に定義する必要がある(非常に手間)
#include<stdio.h>
//このプロトタイプ宣言を入れとけば関数の依存関係は気にしなくて良くなる。
//void a();
//void b();

void a(){
  b();//関数bを呼び出しているが、この呼び出しより上に定義されていないためコンパイルエラー
}
void b(){
  puts("test");
}
int main(){
  a();
}
コンパイルエラー
other/prototype.c:4:3: warning: implicit declaration of function 'b' is invalid in C99
      [-Wimplicit-function-declaration]
  b();
  ^
other/prototype.c:6:6: error: conflicting types for 'b'
void b(){
     ^
other/prototype.c:4:3: note: previous implicit declaration is here
  b();
  ^

mylib.hの内容

void a();
void b();

libtest.cの内容

#include "mylib.h"
main()
{
  a();
  b();
}

もちろんライブラリを利用するプログラムは.hファイルを展開するプリプロセッサを使わなくても 自分でライブラリの中の関数をプロトタイプ宣言に追記すれば利用することができる。ただし、こういうことは面倒なので、基本的には.hファイルを用意して#includeすべき

void a();
void b();
main()
{
  a();
  b();
}

#includeプリプロセッサの利用有無による結果の違い

  • gcc -Eコマンドの結果も大して変わらない

#includeプリプロセッサ利用

$ gcc -E libtest.c mylib.a
clang: warning: mylib.a: 'linker' input unused [-Wunused-command-line-argument]
# 1 "libtest.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 341 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "libtest.c" 2
# 1 "./mylib.h" 1
void a();
void b();
# 2 "libtest.c" 2
main()
{
  a();
  b();
}
$ gcc -E libtest.c mylib.a
clang: warning: mylib.a: 'linker' input unused [-Wunused-command-line-argument]
# 1 "libtest.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 341 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "libtest.c" 2
void a();
void b();
main()
{
  a();
  b();
}

まとめ

ライブラリを作ったなら.hファイルも忘れず作ろう!

おしまい。

プログラミング学習シリーズ C言語改訂版 2 はじめて学ぶCの仕組み

プログラミング学習シリーズ C言語改訂版 2 はじめて学ぶCの仕組み

C言語復習その6。プリプロセッサ、リンカについて

本書ラストのライブラリまで行けると思ったが、時間がなくなった。 もっと有意義に3連休を過ごせなかったのだろうか。(反省)

プログラミング学習シリーズ C言語改訂版 2 はじめて学ぶCの仕組み

プログラミング学習シリーズ C言語改訂版 2 はじめて学ぶCの仕組み

ソースコードから実行ファイル(exe,elf)などができるまで

の処理で処理される。

  • コンパイラは自動的に1,3の処理を呼んでいる
  • 本書の想定だとそれぞれcpp.exe,gcc.exe,ld.exeを使っているようだ
  • cppってC++用のコンパイラだと思っていたのだが...
    • C Preprocessorの略らしい

プリプロセッサ

  • #ハッシュで始まる行を対象に処理をする仕組み

    • #defineで定義されている固定値を置き換える
  • gccでは-Eオプションで実行することにより、プリプロセッサの結果を標準入出力に表示できる

元ソース

#include<stdio.h>
//defineで値を定義
#define bignumber 1000

//マクロを定義
#define max(a,b) (a >b)? a: b

int main(){
  int a = bignumber;
  printf("%d is larger\n", max(100,10));
  printf("%d\n",a);
  printf("%d\n",bignumber);
}

gcc -Eの出力(※stdio.hの展開が巨大すぎるのでそれは略している)

・・・(stdio.hの展開略)

int main(){
  int a = 1000;
  printf("%d is larger\n", (100 >10)? 100: 10);
  printf("%d\n",a);
  printf("%d\n",1000);
}
  • マクロの注意点
    • 関数と違って「型」の情報がない
    • 演算子の優先順位でハマる可能性がある
    • 例えば
int a=5,b=4;
printf("%d\n",max(a, ++b));//6が表示される
int a=5,b=4;
printf("%d\n",(a >++b)? a: ++b);
  • 例2:以下は大きい方に+100された値を期待しているが。。。
    • printf("larger + 100=%d\n",max(20,10)+100);のソースが
    • printf("larger + 100=%d\n",(20 >10)? 20: 10 +100);と展開される
      • この3項演算子(20>10)?10:110となるため評価結果は20となる
    • 出力結果はlarger + 100=20となる。
  • undef#defineで定義した値を取り下げる
# define max 5
printf("%d\n",max);
# undef max
#define max 10
printf("%d\n",max);
- `gcc -E`で以下のように展開される
printf("%d\n",5);


printf("%d\n",10);
  • ifdefでdefineの定義に応じてコードを切り替えられる
    • 昔nmapのソースを読もうと思ったことがあったが、コードに#ifdef DEBUGみたいなのを散見した
    • 多分テストやデバッグ時のコードをプロダクションのバイナリに含まされなくない、というようなことをやっている
  • 組み込みマクロというものもある。
    • コンパイラ?ライブラリ?にあらかじめ用意されている
      • ソースprintf("%s:%d:%s\n",__FILE__,__LINE__,__func__);
      • プリプロセッサ適応後printf("%s:%d:%s\n","chap6/preprocesser.c",39,__func__);
      • 実行結果chap6/preprocesser.c:39:main
        • 正確には__func__はマクロではなく前定義識別名というらしい

リンカ

  • ソース -> 実行ファイルの変換の大トリのやつ。
  • コンパイラ.cファイルから.oファイルにコンパイルするところまでしかやらない。
  • 実際に.oを組み合わせて実行ファイルを作っているのはリンカ。
  • .oファイルは実行ファイル作成時に消されてしまう。
    • gcc に-cオプションをつけることで、リンカの処理を実行しないようにできる

リンカ適応度前適応後のバイナリを比べてみる

  • gcc test.c a.c b.c -o test
  • gcc -c test.c a.c b.c
$ ls -alt
total 72
-rw-r--r--  1   staff   748  7 16 19:13 b.o
-rw-r--r--  1   staff   748  7 16 19:13 a.o
-rw-r--r--  1   staff   672  7 16 19:13 test.o
-rwxr-xr-x  1   staff  8488  7 16 19:13 test
  • test.o:8488Byteのサイズはa.o + b.o + test.o = 2168Byteを大きくうわ待っている
$ hexdump -C test
00000000  cf fa ed fe 07 00 00 01  03 00 00 80 02 00 00 00  |................|
00000010  0f 00 00 00 b0 04 00 00  85 00 20 00 00 00 00 00  |.......... .....|
00000020  19 00 00 00 48 00 00 00  5f 5f 50 41 47 45 5a 45  |....H...__PAGEZE|
00000030  52 4f 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |RO..............|
00000040  00 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000060  00 00 00 00 00 00 00 00  19 00 00 00 d8 01 00 00  |................|
00000070  5f 5f 54 45 58 54 00 00  00 00 00 00 00 00 00 00  |__TEXT..........|
00000080  00 00 00 00 01 00 00 00  00 10 00 00 00 00 00 00  |................|
00000090  00 00 00 00 00 00 00 00  00 10 00 00 00 00 00 00  |................|
000000a0  07 00 00 00 05 00 00 00  05 00 00 00 00 00 00 00  |................|
000000b0  5f 5f 74 65 78 74 00 00  00 00 00 00 00 00 00 00  |__text..........|
000000c0  5f 5f 54 45 58 54 00 00  00 00 00 00 00 00 00 00  |__TEXT..........|
000000d0  20 0f 00 00 01 00 00 00  5d 00 00 00 00 00 00 00  | .......].......|
000000e0  20 0f 00 00 04 00 00 00  00 00 00 00 00 00 00 00  | ...............|
000000f0  00 04 00 80 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000100  5f 5f 73 74 75 62 73 00  00 00 00 00 00 00 00 00  |__stubs.........|
00000110  5f 5f 54 45 58 54 00 00  00 00 00 00 00 00 00 00  |__TEXT..........|
00000120  7e 0f 00 00 01 00 00 00  06 00 00 00 00 00 00 00  |~...............|
00000130  7e 0f 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |~...............|
00000140  08 04 00 80 00 00 00 00  06 00 00 00 00 00 00 00  |................|
00000150  5f 5f 73 74 75 62 5f 68  65 6c 70 65 72 00 00 00  |__stub_helper...|
00000160  5f 5f 54 45 58 54 00 00  00 00 00 00 00 00 00 00  |__TEXT..........|
00000170  84 0f 00 00 01 00 00 00  1a 00 00 00 00 00 00 00  |................|
00000180  84 0f 00 00 02 00 00 00  00 00 00 00 00 00 00 00  |................|
00000190  00 04 00 80 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001a0  5f 5f 63 73 74 72 69 6e  67 00 00 00 00 00 00 00  |__cstring.......|
000001b0  5f 5f 54 45 58 54 00 00  00 00 00 00 00 00 00 00  |__TEXT..........|
000001c0  9e 0f 00 00 01 00 00 00  14 00 00 00 00 00 00 00  |................|
000001d0  9e 0f 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001e0  02 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  5f 5f 75 6e 77 69 6e 64  5f 69 6e 66 6f 00 00 00  |__unwind_info...|
00000200  5f 5f 54 45 58 54 00 00  00 00 00 00 00 00 00 00  |__TEXT..........|
00000210  b4 0f 00 00 01 00 00 00  48 00 00 00 00 00 00 00  |........H.......|
00000220  b4 0f 00 00 02 00 00 00  00 00 00 00 00 00 00 00  |................|
00000230  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000240  19 00 00 00 e8 00 00 00  5f 5f 44 41 54 41 00 00  |........__DATA..|
00000250  00 00 00 00 00 00 00 00  00 10 00 00 01 00 00 00  |................|
00000260  00 10 00 00 00 00 00 00  00 10 00 00 00 00 00 00  |................|
00000270  00 10 00 00 00 00 00 00  07 00 00 00 03 00 00 00  |................|
00000280  02 00 00 00 00 00 00 00  5f 5f 6e 6c 5f 73 79 6d  |........__nl_sym|
00000290  62 6f 6c 5f 70 74 72 00  5f 5f 44 41 54 41 00 00  |bol_ptr.__DATA..|
000002a0  00 00 00 00 00 00 00 00  00 10 00 00 01 00 00 00  |................|
000002b0  10 00 00 00 00 00 00 00  00 10 00 00 03 00 00 00  |................|
000002c0  00 00 00 00 00 00 00 00  06 00 00 00 01 00 00 00  |................|
000002d0  00 00 00 00 00 00 00 00  5f 5f 6c 61 5f 73 79 6d  |........__la_sym|
000002e0  62 6f 6c 5f 70 74 72 00  5f 5f 44 41 54 41 00 00  |bol_ptr.__DATA..|
000002f0  00 00 00 00 00 00 00 00  10 10 00 00 01 00 00 00  |................|
00000300  08 00 00 00 00 00 00 00  10 10 00 00 03 00 00 00  |................|
00000310  00 00 00 00 00 00 00 00  07 00 00 00 03 00 00 00  |................|
00000320  00 00 00 00 00 00 00 00  19 00 00 00 48 00 00 00  |............H...|
00000330  5f 5f 4c 49 4e 4b 45 44  49 54 00 00 00 00 00 00  |__LINKEDIT......|
00000340  00 20 00 00 01 00 00 00  00 10 00 00 00 00 00 00  |. ..............|
00000350  00 20 00 00 00 00 00 00  28 01 00 00 00 00 00 00  |. ......(.......|
00000360  07 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
00000370  22 00 00 80 30 00 00 00  00 20 00 00 08 00 00 00  |"...0.... ......|
00000380  08 20 00 00 18 00 00 00  00 00 00 00 00 00 00 00  |. ..............|
00000390  20 20 00 00 10 00 00 00  30 20 00 00 40 00 00 00  |  ......0 ..@...|
000003a0  02 00 00 00 18 00 00 00  78 20 00 00 06 00 00 00  |........x ......|
000003b0  e8 20 00 00 40 00 00 00  0b 00 00 00 50 00 00 00  |. ..@.......P...|
000003c0  00 00 00 00 00 00 00 00  00 00 00 00 04 00 00 00  |................|
000003d0  04 00 00 00 02 00 00 00  00 00 00 00 00 00 00 00  |................|
000003e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000003f0  d8 20 00 00 04 00 00 00  00 00 00 00 00 00 00 00  |. ..............|
00000400  00 00 00 00 00 00 00 00  0e 00 00 00 20 00 00 00  |............ ...|
00000410  0c 00 00 00 2f 75 73 72  2f 6c 69 62 2f 64 79 6c  |..../usr/lib/dyl|
00000420  64 00 00 00 00 00 00 00  1b 00 00 00 18 00 00 00  |d...............|
00000430  01 a0 6d a0 dc d8 3b 93  b9 e4 c3 d8 18 65 02 c8  |..m...;......e..|
00000440  24 00 00 00 10 00 00 00  00 0d 0a 00 00 0d 0a 00  |$...............|
00000450  2a 00 00 00 10 00 00 00  00 00 00 00 00 00 00 00  |*...............|
00000460  28 00 00 80 18 00 00 00  20 0f 00 00 00 00 00 00  |(....... .......|
00000470  00 00 00 00 00 00 00 00  0c 00 00 00 38 00 00 00  |............8...|
00000480  18 00 00 00 02 00 00 00  04 32 e4 04 00 00 01 00  |.........2......|
00000490  2f 75 73 72 2f 6c 69 62  2f 6c 69 62 53 79 73 74  |/usr/lib/libSyst|
000004a0  65 6d 2e 42 2e 64 79 6c  69 62 00 00 00 00 00 00  |em.B.dylib......|
000004b0  26 00 00 00 10 00 00 00  70 20 00 00 08 00 00 00  |&.......p ......|
000004c0  29 00 00 00 10 00 00 00  78 20 00 00 00 00 00 00  |).......x ......|
000004d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000f20  55 48 89 e5 b0 00 e8 15  00 00 00 b0 00 e8 2e 00  |UH..............|
00000f30  00 00 31 c0 5d c3 90 90  90 90 90 90 90 90 90 90  |..1.]...........|
00000f40  55 48 89 e5 48 83 ec 10  48 8d 3d 4f 00 00 00 e8  |UH..H...H.=O....|
00000f50  2a 00 00 00 89 45 fc 48  83 c4 10 5d c3 90 90 90  |*....E.H...]....|
00000f60  55 48 89 e5 48 83 ec 10  48 8d 3d 38 00 00 00 e8  |UH..H...H.=8....|
00000f70  0a 00 00 00 89 45 fc 48  83 c4 10 5d c3 90 ff 25  |.....E.H...]...%|
00000f80  8c 00 00 00 4c 8d 1d 7d  00 00 00 41 53 ff 25 6d  |....L..}...AS.%m|
00000f90  00 00 00 90 68 00 00 00  00 e9 e6 ff ff ff 61 20  |....h.........a |
00000fa0  63 61 6c 6c 65 64 00 62  28 29 20 63 61 6c 6c 65  |called.b() calle|
00000fb0  64 00 00 00 01 00 00 00  1c 00 00 00 00 00 00 00  |d...............|
00000fc0  1c 00 00 00 00 00 00 00  1c 00 00 00 02 00 00 00  |................|
00000fd0  20 0f 00 00 34 00 00 00  34 00 00 00 7e 0f 00 00  | ...4...4...~...|
00000fe0  00 00 00 00 34 00 00 00  03 00 00 00 0c 00 01 00  |....4...........|
00000ff0  10 00 01 00 00 00 00 00  00 00 00 01 00 00 00 00  |................|
00001000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001010  94 0f 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
00001020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002000  11 22 10 51 00 00 00 00  11 40 64 79 6c 64 5f 73  |.".Q.....@dyld_s|
00002010  74 75 62 5f 62 69 6e 64  65 72 00 51 72 00 90 00  |tub_binder.Qr...|
00002020  72 10 11 40 5f 70 75 74  73 00 90 00 00 00 00 00  |r..@_puts.......|
00002030  00 01 5f 00 05 00 04 5f  6d 68 5f 65 78 65 63 75  |.._...._mh_execu|
00002040  74 65 5f 68 65 61 64 65  72 00 27 6d 61 69 6e 00  |te_header.'main.|
00002050  2b 61 00 30 62 00 35 02  00 00 00 03 00 a0 1e 00  |+a.0b.5.........|
00002060  03 00 c0 1e 00 03 00 e0  1e 00 00 00 00 00 00 00  |................|
00002070  a0 1e 20 20 00 00 00 00  02 00 00 00 0f 01 10 00  |..  ............|
00002080  00 00 00 00 01 00 00 00  16 00 00 00 0f 01 00 00  |................|
00002090  40 0f 00 00 01 00 00 00  19 00 00 00 0f 01 00 00  |@...............|
000020a0  60 0f 00 00 01 00 00 00  1c 00 00 00 0f 01 00 00  |`...............|
000020b0  20 0f 00 00 01 00 00 00  22 00 00 00 01 00 00 01  | .......".......|
000020c0  00 00 00 00 00 00 00 00  28 00 00 00 01 00 00 01  |........(.......|
000020d0  00 00 00 00 00 00 00 00  04 00 00 00 05 00 00 00  |................|
000020e0  00 00 00 40 04 00 00 00  20 00 5f 5f 6d 68 5f 65  |...@.... .__mh_e|
000020f0  78 65 63 75 74 65 5f 68  65 61 64 65 72 00 5f 61  |xecute_header._a|
00002100  00 5f 62 00 5f 6d 61 69  6e 00 5f 70 75 74 73 00  |._b._main._puts.|
00002110  64 79 6c 64 5f 73 74 75  62 5f 62 69 6e 64 65 72  |dyld_stub_binder|
00002120  00 00 00 00 00 00 00 00                           |........|
$ hexdump -C test.o
00000000  cf fa ed fe 07 00 00 01  03 00 00 00 01 00 00 00  |................|
00000010  04 00 00 00 b0 01 00 00  00 20 00 00 00 00 00 00  |......... ......|
00000020  19 00 00 00 38 01 00 00  00 00 00 00 00 00 00 00  |....8...........|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  78 00 00 00 00 00 00 00  d0 01 00 00 00 00 00 00  |x...............|
00000050  78 00 00 00 00 00 00 00  07 00 00 00 07 00 00 00  |x...............|
00000060  03 00 00 00 00 00 00 00  5f 5f 74 65 78 74 00 00  |........__text..|
00000070  00 00 00 00 00 00 00 00  5f 5f 54 45 58 54 00 00  |........__TEXT..|
00000080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000090  16 00 00 00 00 00 00 00  d0 01 00 00 04 00 00 00  |................|
000000a0  48 02 00 00 02 00 00 00  00 04 00 80 00 00 00 00  |H...............|
000000b0  00 00 00 00 00 00 00 00  5f 5f 63 6f 6d 70 61 63  |........__compac|
000000c0  74 5f 75 6e 77 69 6e 64  5f 5f 4c 44 00 00 00 00  |t_unwind__LD....|
000000d0  00 00 00 00 00 00 00 00  18 00 00 00 00 00 00 00  |................|
000000e0  20 00 00 00 00 00 00 00  e8 01 00 00 03 00 00 00  | ...............|
000000f0  58 02 00 00 01 00 00 00  00 00 00 02 00 00 00 00  |X...............|
00000100  00 00 00 00 00 00 00 00  5f 5f 65 68 5f 66 72 61  |........__eh_fra|
00000110  6d 65 00 00 00 00 00 00  5f 5f 54 45 58 54 00 00  |me......__TEXT..|
00000120  00 00 00 00 00 00 00 00  38 00 00 00 00 00 00 00  |........8.......|
00000130  40 00 00 00 00 00 00 00  08 02 00 00 03 00 00 00  |@...............|
00000140  00 00 00 00 00 00 00 00  0b 00 00 68 00 00 00 00  |...........h....|
00000150  00 00 00 00 00 00 00 00  24 00 00 00 10 00 00 00  |........$.......|
00000160  00 0d 0a 00 00 00 00 00  02 00 00 00 18 00 00 00  |................|
00000170  60 02 00 00 03 00 00 00  90 02 00 00 10 00 00 00  |`...............|
00000180  0b 00 00 00 50 00 00 00  00 00 00 00 00 00 00 00  |....P...........|
00000190  00 00 00 00 01 00 00 00  01 00 00 00 02 00 00 00  |................|
000001a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001d0  55 48 89 e5 b0 00 e8 00  00 00 00 b0 00 e8 00 00  |UH..............|
000001e0  00 00 31 c0 5d c3 00 00  00 00 00 00 00 00 00 00  |..1.]...........|
000001f0  16 00 00 00 00 00 00 01  00 00 00 00 00 00 00 00  |................|
00000200  00 00 00 00 00 00 00 00  14 00 00 00 00 00 00 00  |................|
00000210  01 7a 52 00 01 78 10 01  10 0c 07 08 90 01 00 00  |.zR..x..........|
00000220  24 00 00 00 1c 00 00 00  a8 ff ff ff ff ff ff ff  |$...............|
00000230  16 00 00 00 00 00 00 00  00 41 0e 10 86 02 43 0d  |.........A....C.|
00000240  06 00 00 00 00 00 00 00  0e 00 00 00 02 00 00 2d  |...............-|
00000250  07 00 00 00 01 00 00 2d  00 00 00 00 01 00 00 06  |.......-........|
00000260  01 00 00 00 0f 01 00 00  00 00 00 00 00 00 00 00  |................|
00000270  0a 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
00000280  07 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
00000290  00 5f 6d 61 69 6e 00 5f  62 00 5f 61 00 00 00 00  |._main._b._a....|
000002a0

ふむふむなるほど(無能)

結局意味がわからないので特に何も書くことがない。 とりあえずcatで連結するような単純なものではないらしい。

感想

リンカは結構単純な置換をやっているだけに見えるが、 ruiさんが

Cプリプロセッサの実装はかなり手間がかかる。

qiita.com

と書かれていたり

コンパイラの入門書で作成対象外になっていたりなどで

本書では、この4つの段階のうちプリプロセスを除いた、コンパイルアセンブル・リンクについてお話しします(普通のコンパイラを作ろうp8より)

作るとなると意外と難しいものなのかもしれない。