POSTD PRODUCED BY NIJIBOX

POSTD PRODUCED BY NIJIBOX

ニジボックスが運営する
エンジニアに向けた
キュレーションメディア

POSTD PRODUCED BY NIJIBOX

POSTD PRODUCED BY NIJIBOX

ニジボックスが運営する
エンジニアに向けた
キュレーションメディア

FeedlyRSSTwitterFacebook
Tadeu Zagallo

本記事は、原著者の許諾のもとに翻訳・掲載しております。

背景




 Programming from the Ground Up 11

Linux x86 GNU64Mac OS X i386  x86_64 

 i386  exit  %ebx  x86_64  0x2000000  int $0x80  syscall 使

x86PC使便

Facebookx86

  Uri Baghin


x86 0 
# program.s

 .section __TEXT,__text
  .globl start
start:
  mov $0x1, %eax
  push $0x0
  call _syscall

_syscall:
  int $0x80

Mac OS Xで上記のプログラムをビルドする方法は以下の通りです。

$ as -static -arch i386 -o program.o program.s
$ ld -static -arch i386 -o program program.o

テストするために、次のコマンドで実行と終了コードの確認ができます。

$ ./program
$ echo $?

2

Mach-O




Mach-O Binary image
  MachOView 調便

 LC_SEGMENT 

LC_SEGMENT 


 LC_SEGMENT 



 __TEXT 

VM

VM使





VMVM

VMVM



 mach-o/loader.h  struct segment_command 


VM File Offset  File Offset + File Size  VM Address  VM Address + VM Size  ArrayBuffer 

 LC_UNIXTHREAD 

 %eip PC使


  x86

x86 Instruction Format
KISSKeep It Simple, Stupid objdump  objdump  binutils CLI
$ brew install binutils # if you don't have it installed yet
$ gobjdump -d program

Disassembly of section .text:

00001ff2 <start>:
    1ff2:       b8 01 00 00 00          mov    $0x1,%eax
    1ff7:       6a 00                   push   $0x0
    1ff9:       e8 00 00 00 00          call   1ffe <_syscall>

00001ffe <_syscall>:
    1ffe:       cd 80                   int    $0x80

機能を全て整えたエミュレータを実装しようとは思っていなかったため、とりあえず必要なオペコードのシンタックスを探したところ、x86向けの適切なリファレンス http://ref.x86asm.net/coder.html が見つかりました。

そこで、オペコードから関数へのマップ(本当にプレーンなJavaScriptオブジェクトで実装しました)を作成しました。関数は、オペコードにより必要となれば、より多くのデータを読み取るための役割を担います。例えば次のようなものがあります。

var Functions = {};
Functions[0x6a] = function () {
  // Push one byte
  push(read(1));
};

読み込んだオペコードが実はオペコードの接頭語だった場合は、次のバイトにある実際のオペコードを読み取らなければなりません。

var Fn0x0f = {
  // jge
  0x8d: function () {
    var dist = read(4);
    if (!NG) {
      PC += dist;
    }
  },
  // ...
};

Functions[0x0f] = function () {
  // Call the actual function inside the prefix
  var fn = read(1);
  Fn0x0f[fn]();
};

最後に取り上げたいのは、システムコールです。実際にシミュレートする必要があるため、システムコール番号から関数へのマップをもう一つ使います。

var Syscalls = {};
Syscalls[0x01] = function () {
  // Fake exit, since there's no OS
  console.log('Program returned %s', Stack[Registers[ESP + 1]]);
  PC = -1; // Mark the program as ended by setting the program counter to -1
};

 File API 使html input 


 gist 3 mach-o.js  x86.js  index.html C

libcC -static nostdlib 



 C  clang -O3  fibonacci(40)  947 

 HackerNews    DataView  Uint8Array  fibonacci(40)  153    Perl  ruby 1.8 
監修者
監修者_古川陽介
古川陽介
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
複合機メーカー、ゲーム会社を経て、2016年に株式会社リクルートテクノロジーズ(現リクルート)入社。 現在はAPソリューショングループのマネジャーとしてアプリ基盤の改善や運用、各種開発支援ツールの開発、またテックリードとしてエンジニアチームの支援や育成までを担う。 2019年より株式会社ニジボックスを兼務し、室長としてエンジニア育成基盤の設計、技術指南も遂行。 Node.js 日本ユーザーグループの代表を務め、Node学園祭などを主宰。