ウホウホゴリラッホ

主に勉強したことをまとめていきます。twitter:@pytran3

アセンブリ勉強記録 7

勉強したこと

ポインタ

ポインタの指し先を書き換える場合はデータ長を指定しないといけない。

mov [test], 4 ; <- compile error
mov byte[test], 4 ; <- ok!!

文字列

コードを写経した。基本的にこういうロジックはC言語で学んだことと同じくやるらしい。

global _start

section .data

test_string: db "abcdef", 0

section .text

strlen:
    xor rax, rax

.loop:
    cmp byte [rdi+rax], 0

    je .end
    inc rax
    jmp .loop

.end:
    ret

_start:
    mov rdi, test_string
    call strlen
    mov rdi, rax
    mov rax, 60
    syscall

呼び出し先退避レジスタ

絶対忘れる。

システムコール

Linuxのmanコマンドを使うと定義が確認できる。C言語での説明が書かれているが、引数の順序が一致しているらしい。上手くアセンブリに読み替えながら解読していくものらしい。。。

https://montcs.bloomu.edu/Information/LowLevel/Assembly/assembly-tutorial.html

アセンブリ勉強記録 6

勉強したこと

call

call <address>は以下の糖衣構文らしい

push rip
jmp <adress>

ripはリターンアドレスを表す。

ret

retpop ripは同じ意味らしい?

return a value

raxに戻り値を格納する。rdxも同様の役割をもつらしく、第2の戻り値として利用される。

システムコール

引数の仕様が関数とは違うことに注意。関数の第4引数はrcxだが、システムコールr10を用いる。

アセンブリ勉強記録 4

勉強したこと

syscall

linuxシステムコールのテーブルは以下で定義されている。カーネルが立ち上がるときにハンドラがこのように登録される。

linux/syscall_64.tbl at v4.15 · torvalds/linux · GitHub

system callの実装はこのへんのどこかにあるはず

linux/arch/x86/kernel at v4.15 · torvalds/linux · GitHub

アセンブリ勉強記録 3

勉強したこと

NASMでの実行ファイルの生成

リンクする必要があるらしい。

nasm -felf64 main.asm
ld -o main main.o

徒然

  • movではメモリtoメモリのコピーができないらしい。レジスタ<->メモリはできるのかな?
  • syscallで呼び出されるシステムコールカーネル依存なので、仕様を確認する場合にはそちらを見る必要がある?
    • 追記、っぽい。カーネル起動時に割り込みテーブルを設定するらしい。OSの無いシステムは特権周りどうしてるんだろう

www.mztn.org

アセンブリ勉強記録 2

勉強したこと

ハードウェアスタック

スタックをハードウェアでサポートしており、rspレジスタを利用する。
rspレジスタにはスタックの最も上にある要素のアドレスが格納される。オペランドのサイズは通常8バイトを使うが2,4バイトも使える。

stack overflowはrspが確保した領域外を指してしまうことらしい。Segmentation faultが発生する。

コンパイラ

GASとNASMがある。微妙に記法が違うっぽくて間違えるとコンパイルが通らない。

_start

リンクされたプログラムのデフォルトのエントリーポイントとして使用されるラベル。

 参考文献

GitHub - IBM/japan-technology: IBM Related Japanese technical documents - Code Patterns, Learning Path, Tutorials, etc.

アセンブリ勉強記録

動機

コンパイラを書くにあたって、アセンブリの知識が無いと難しいことがわかったので平行して勉強していこうかと。
最初の目標は再帰関数でフィボナッチ数を計算することにした。

勉強したこと

おまじないたち

おまじない扱いされてそうな彼ら

.intel_syntax noprefix

INTEL記法で書きますよ!という宣言。noprefixとはどういう意味だろうか。。。

.blobl main

アセンブリ上でのブローバルな変数、関数を宣言している。

mul

対応するAレジスタと掛け算を実行して、そのAレジスタに格納する。
addと違う書き方になる。物理的な回路の制約からこうなっているのだろうか・・・?

call

引数の関数(ラベル?)にジャンプする。retで一つ前のcallにジャンプするのを忘れない。retではスタックを一つ戻したりしてるらしい。

今日書いたコード

掛け算と関数呼び出しを実装した。 ださい関数名してるけど、衝突しにくいから良い命名規則な気がする。

.intel_syntax noprefix
.globl main

kakeru:
    mov rdx, rdi
    mov rax, rsi
    mul rdx
    mov rax, rax
    ret

main:
    mov rdi, 13
    mov rsi, 2
    call kakeru
    ret