結構序盤であった話、
こんな質問がありました。
パソコンは0と1の情報だけで命令を出すんでしょ。
なんで、
var a = 5; var b = 6; if ( a > b ) { document.write(a); } else { document.write(b); }
数字を一切書かなくても実行することができるの?と
これが実行の際に、コンピュータがね、このコードを0と1の形に変換してから実行するんだよ
と伝えても、納得できないし、話してる自分もなんか嫌だ。
ということで、
C言語を勉強して、Cのコードをアセンブリ言語に変換した後、アセンブラでバイナリの実行ファイルを生成する流れを見せようと
苦しんで覚えるC言語、通称くるCと
教養としてのコンピュータ・サイエンス (Information Science&Engineering)
国立大学の一年向けに書かれた教科書がわかりやすいということで、
これらの本を元にコンピュータの勉強を始めるのでした。
とりあえず、Cで似たようなコードを書く。
hoge.c
#include <stdio.h> void main() { int a; int b; a = 5; b = 6; if ( a > 5 ) { printf("%d", a); } else { printf("%d", b); } }
このコードをターミナルを開いて、
gcc -S hoge.c
のアセンブラ化と
gcc hoge.c
の実行ファイルへのコンパイルを行い、これらのファイルを表示してみせる。
アセンブラへの変換を行った結果が、
hoge.s
.file"hoge.c" .section .rodata .LC0: .string "%d" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movl $5, -8(%rbp) movl $6, -4(%rbp) cmpl $5, -8(%rbp) jle .L2 movl -8(%rbp), %eax movl %eax, %esi movl $.LC0, %edi movl $0, %eax call printf jmp .L4 .L2: movl -4(%rbp), %eax movl %eax, %esi movl $.LC0, %edi movl $0, %eax call printf .L4: nop leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413" .section .note.GNU-stack,"",@progbits
こんな感じで、シンボルを予想しながら読んでもらう。
コンパイルしたa.outも表示する。
(今回は例を表示するためにバイナリエディタのGHexを使用しています。)
Ghex - Free Software Directory
GHexに表示されている内容は0と1ではないけれど、
値はすべて16進法なので、イメージフル回転で2進法だと感じ取ってくれ
でなんとか実行のイメージを見せることができた。
(アセンブラ化したコードを上から順に16進法の数字に変換している)
人に教えることは自分を試すことだとよく言われるけど、
こんなにもたくさんのことを見ることになるとは思ってもいなかったよ。
あとで読んだものだけど、
O'Reilly Japan - コンピュータシステムの理論と実装
コンピュータが0と1で動いていることを実感する上で、
オライリーのコンピュータシステムの理論と実装が半端無く良かった。