Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RG-Arch 輪講資料: Binary Hacks Rebooted 数値演算など
Search
kota-yata
October 20, 2025
Programming
0
20
RG-Arch 輪講資料: Binary Hacks Rebooted 数値演算など
kota-yata
October 20, 2025
Tweet
Share
More Decks by kota-yata
See All by kota-yata
結局QUICで通信は速くなるの?
kota_yata
10
7.8k
RG-Arch輪考資料: QUIC is not Quick Enough over Fast Internet
kota_yata
0
110
RG-Arch輪考資料: Implementation and Performance Evaluation of the QUIC Protocol in Linux Kernel
kota_yata
0
120
2024年秋 中村研 WIP発表資料
kota_yata
0
64
パタヘネ輪読: 第五章
kota_yata
0
30
パタヘネ輪読: 第一章
kota_yata
0
210
2023年秋 中村研 WIP発表資料
kota_yata
0
110
2023年春 中澤大越研 WIP発表資料
kota_yata
0
65
BigIntの良いとこ悪いとこ
kota_yata
0
100
Other Decks in Programming
See All in Programming
What's New in Web AI?
christianliebel
PRO
0
120
O Que É e Como Funciona o PHP-FPM?
marcelgsantos
0
260
Researchlyの開発で参考にしたデザイン
adsholoko
0
120
Making Angular Apps Smarter with Generative AI: Local and Offline-capable
christianliebel
PRO
0
110
Nitro v3
kazupon
2
210
AsyncSequenceとAsyncStreamのプロポーザルを全部読む!!
s_shimotori
1
250
Pythonに漸進的に型をつける
nealle
1
160
Migration to Signals, Resource API, and NgRx Signal Store
manfredsteyer
PRO
0
160
釣り地図SNSにおける有料機能の実装
nokonoko1203
0
210
CSC509 Lecture 10
javiergs
PRO
0
170
CSC509 Lecture 08
javiergs
PRO
0
280
詳細の決定を遅らせつつ実装を早くする
shimabox
1
920
Featured
See All Featured
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
Making the Leap to Tech Lead
cromwellryan
135
9.6k
Product Roadmaps are Hard
iamctodd
PRO
55
11k
Bash Introduction
62gerente
615
210k
Optimizing for Happiness
mojombo
379
70k
Site-Speed That Sticks
csswizardry
13
960
Mobile First: as difficult as doing things right
swwweet
225
10k
KATA
mclloyd
PRO
32
15k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.3k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.3k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Transcript
Binary Hacks Rebooted イントロ, 数値演算 RG Arch輪講第1回 Presenter: Arch B3
Kota
⽬次 • 1章: イントロダクション ◦ fileコマンドを使わずにファイルの種類を調べる ◦ libcのwrite()を使った標準出⼒ • 7章:
数値表現とデータ処理Hack ◦ 符号付き整数 ◦ エンディアン ◦ 固定⼩数点数 ◦ 可変⻑表現(Zig-zag, UTF-8) ◦ 浮動⼩数点数 ◦ NaN 2
1章-fileコマンドを使わずにファイルの種類を調べる 3 • fileコマンドは特定のファイルの形式,属性を調べるUnixコマンド ◦ 拡張⼦がなくても調べられる • 多くのファイルにはマジックナンバーがあり,最初の数バイトを⾒ると種類が 分かる ◦
e.g. jpgはffd8ffe0,gzipは1f8b ◦ https://en.wikipedia.org/wiki/List_of_file_signatures • コマンド⾃体のhexdumpをするとELFのマジックナンバーが⾒えたりする ◦ Unixにおいて「全てはファイル」 • 古い.tarなどはマジックナンバーを持たず,独⾃の判定ロジックがある
1章-libcのwrite()を使った標準出⼒ 4 • Unix系のOS(Mac OSやLinux OS)においてはファイルディスクリプタの1番 は標準出⼒にアサインされている ◦ ちなみに0番は標準⼊⼒,2番は標準エラー出⼒ ◦
ターミナルが標準出⼒”ファイル”を開いているというイメージ • print(“Hello world!”)は実質標準出⼒ファイルに書き込みしているのと⼀緒 • つまりwrite()でもprintと同じことができる!
7章 数値表現とデータ処理Hack 5
符号なし整数と符号付き整数 • 整数の表現⽅法として符号なし整数と符号付き整数がある(uint, int) • 符号なし整数は2進整数をそのまま表現する ◦ 7 = 00000111(uint8の場合)
• 符号あり整数の場合,表現できる最⼤値の下半分は正の値に使い,上半分は補 数を⽤いて負の値を表現する 6
符号付き整数(int8の例) 7 • 00000000~01111111までは正の値の表現に使う ◦ 符号なし整数と同様の表現⽅法(7=00000111) • 10000000~11111111までは負の値の表現に使う ◦ 「その値の絶対値を⾜したらちょうど桁上がりする値」を負の値とする
◦ 7の2進数表現は00000111なので11111001を⾜せば桁上がりする ◦ これを2の補数表現という • 結果的に8ビットで-128~127を表現できる
補数表現を使うことのメリット 例:-7 -> 0b10000111 とすれば下位7ビットは符号なし整数と同じ.. • 減算を加算で表現できる ◦ 例:7-8を7+(-8)とする ◦
0b00000111 + 0b11111000 = 0b11111111 = -1 ◦ 負の値同⼠の加算もオーバーフローを無視すれば同様に演算が可能 • 0が⼀意に決まる ◦ ⼀番上の例だと+0と-0という⼆つの0が誕⽣する ◦ 0が⼀意に決まる(0b0)補数表現の⽅が楽 8 「MSBを符号ビットとすればそのあとは値をそのまま格納できて直感的では?」
符号拡張 9 • CPUアーキテクチャによっては8ビットや16ビットの変数に対応する幅の命令 がない場合がある ◦ x86-64では切り離せなかった後⽅互換性により8, 16, 32, 64ビット全ての幅に対す
る整数演算命令がある ◦ Arm64など⽐較的新しいアーキテクチャでは32ビットと64ビット幅の整数演算命令 しかない • 演算の前後でレジスタのビット幅に合致するように値を拡張する必要がある ◦ 上位に挿⼊する各桁を符号ビットと同じ値にすれば良い ◦ e.g. 11111001 -> 1111111111111001
エンディアン 10 • 値の上位,下位桁をメモリの上位,下位バイトのどちらと対応させるか ◦ ビッグエンディアン:値の上位がメモリの下位 ◦ リトルエンディアン:値の上位がメモリの上位 例:0xABCDEF01という値を格納する時 メモリ下位
メモリ上位
エンディアン 11 • ネットワークパケットのヘッダー情報はビッグエンディアンと定められている ◦ これはネットワークバイトオーダーと呼ばれる ◦ 各プロトコルで明確に定められているというよりはRFC1700などで慣習として記さ れている •
⼀⽅エンド端末では⼀般にリトルエンディアンが⽤いられる ◦ 幅が異なる変数にキャストした時とかに下位ビットが保持されるメリットがある ◦ ネットワークパケットを作る際はhton関数で変換するのが⼀般的 ◦ x86_64にはbswapやmovbe(拡張命令セット)などの変換命令がある
固定⼩数点数 12 • ⼩数点以下のビット数が固定されている数値型 • 整数部分を8ビット,⼩数部分を8ビットとする符号付き固定⼩数点がある時分 解能は1/256になる(最⼤値は127.996くらい) ◦ 精度がある程度分かっている値を扱う際は固定⼩数点で⼗分なケースがある •
ハードウェア的には整数演算と同じユニットを使えるため,浮動⼩数点と⽐較 して演算の効率が良い
可変⻑表現 13
可変⻑表現 14 • 整数を表現するビット列から冗⻑な部分を取り除いて必要最⼩限のビット数に 圧縮する技術 ◦ WebAssemblyの整数値の格納にはLEB128が使われている ▪ 各バイトについてMSBを継続ビットとし,下位7ビットを実際の数値とする ▪
5 -> 00000101, 300 -> 10101100 00000010 ◦ Protocol BufferではZig-zagエンコーディングが使われている
可変⻑表現-Zig-zagエンコーディング 15 • 2の補数を⽤いる符号付き整数とは対照的に,LSBを符号ビットとする ◦ 0b00000000: 0 ◦ 0b00000001: -1
◦ 0b00000010: 1 ◦ 0b00000011: -2 ◦ 0b00000100: 2 ◦ … ◦ 0b01111111: -127 ◦ 0b11111110: 127 ◦ 0b11111111: -128 例:-1を符号付き整数で表現したい時 • 2の補数表現の場合LEB128で10バイト • Zig-zagを使えばLEB128で1バイト! ⼩さな値は必ず少ないバイト数で表現できる
UTF-8 • LEB128とかなり似ている ◦ 継続ビットを⽤いる点では同じ 16 漢字は⼤体hex4桁なので3バイト必要🥺
おまけ:UTF-16 17 • Unicodeコードポイント U+0000〜U+FFFFはそのまま2バイトで表現 ◦ ⽇本語の常⽤漢字も2バイト! • U+10000〜U+10FFFFは「サロゲート」に分割される ◦
UnicodeにおいてU+D800〜U+DBFFは上位サロゲート,U+DC00〜U+DFFFは下位 サロゲートという予約領域になっている ◦ コードポイント-0x10000をして,結果の上位10ビットを上位,下位10ビットを下 位サロゲートに格納
UTF-16エンコードの例 18 • 0x1F97A - 0x10000 = 0xF97A = 0b00001111100101111010(20ビット)
• 上位10桁と0xD800(上位サロゲートのベース値)と⾜す -> 0xD83E • 残りの桁と0xDC00(下位サロゲートのベース値)と⾜す -> 0xDD7A 🥺はD8 3E DD 7Aの4バイトにエンコードされる 🥺 (U+1F97A)
浮動⼩数点 19
浮動⼩数点数 20 • ⼩数を含む値を仮数部,指数部分に分けて表現する ◦ sが符号ビット,mが仮数部,eが指数部 ◦ b(基数)は⼀般には2(IEEE 754).IEEE754-2008で基数10の仕様が追加された ◦
基数10の例:125.5 = 1.255 * 10^2 ◦ 基数2の例:0.01(10進数で0.25)= 1.0 * 2^-2
浮動⼩数点の正規化 21 • IEEE754では,浮動⼩数点の仮数部は常に”正規化”される ◦ 仮数部のMSBが0でない数になる(e.g. 0.034 -> 3.4, 0.254
-> 2.54) ◦ つまり2進数で表現する時,整数部分は必ず1になるように指数が調整される ▪ e.g. 0.00101 -> 1.01 * 2^-3 ▪ 必ず1なので,実際には仮数部は⼩数点以下から格納される(ケチ表現) • 指数部は”バイアス”をかけて符号なし整数にする ◦ 例えば指数部が8ビットだった場合,実際の値+127をする ◦ 本来-126~127の値が,1~254になる(0は0.0, 255はNaNとinfiniteの表現に使う)
浮動⼩数点のデータ構造 22 • 指数部はバイアスがかかっているので符号なし整数 • 仮数部は⼩数点以下の値を格納
浮動⼩数点の加算 23 • 加算対象の⼆つの値の内指数が⼤きい⽅に合わせる ◦ 1.111 * 2^2 + 1.011
* 2^3の場合指数3に合わせる ◦ 1.111 * 2^2 -> 0.1111 * 2^3 ◦ この段階で⽚⽅の精度が落ちる • 指数を合わせたら仮数部を⾜す ◦ 0.1111 + 1.011 = 10.0101 • 正規化する ◦ 1.00101 * 2^4
丸め 24 • 多くの演算では加算時に桁上がりが発⽣し,値を丸める必要が出てくる • 最もよく使われる丸めかたは”roundTiesToEven” ◦ 最も近い浮動⼩数点数に丸める.ちょうど中間ならLSBが0の⽅に丸める ◦ 例:1.10001₂(=1.53125₁₀)はちょうど1.1000₂
(=1.5₁₀)と1.1001₂ (=1.5625₁₀)の間 ▪ この場合LSBが0の1.1000₂に合わせる • この丸めによってfloat同⼠の等価演算がfalseになったりする ◦ 0.1 + 0.2 !== 0.3 とか
25 NaNの種類
NaNは2種類ある Signaling NaN 26 • 演算の⼊⼒に含まれているとinvalid operation例外を発⽣させる • 未初期化変数を誤って演算に使った際などの検出に使う Quiet
NaN • 主に数値演算の結果として⽣成されるNaN • 演算時のinvalid operationの結果はデフォルトでquite NaN 表現としては,仮数部のMSBが1ならquiet NaN,0ならsignaling NaN…
実はそうとも限らない 27 • IEEE754-1985の時点では⼆種類のNaNの区別はされていなかった • 前述のような区別がなされたのはIEEE754-2008から • MIPSやPA-RISCなど古のアーキテクチャではquite NaNでもMSBが⽴っていな い場合がある
• とはいえ現代的なアーキテクチャであればほとんどIEEE754-2008の仕様通り の実装になっている
Signaling NaNを作ってみよう! 28 • 実際に⼿動でSignaling NaNを作って,演算の⼊⼒に含めてみる • 演算結果がQuite NaNになり,Invalid Operationフラグが⽴つかどうかを確か
めてよう! できたコードがこちら→
学べたこと 29 • 符号付き,符号なしの整数表現と2の補数表現 • 符号拡張,エンディアン,固定⼩数点 • 浮動⼩数点の表現⽅法と演算 • NaNの種類