コード
section .text
global _ft_strcpy
_ft_strcpy:
push rbp
mov rbp, rsp
push rdi
.copy:
cmp BYTE [rsi], 0
je .end
movsb
jmp .copy
.end:
mov BYTE [rdi], 0
pop rax
leave
ret
今回使用したレジスタ
今回は、スタックフレームを使用するため、冒頭と最後でプロローグ、エピローグという処理をしています。
レジスタ | 意味 |
---|---|
rax | 汎用レジスタ |
rsi | ストリング型の命令でコピー元(ソース)を示す場合に専用に使われます。 |
rdi | ストリング型の命令でコピー先(デスティネーション)を示す場合に専用に使われます。 |
bl | rbx(ベースレジスタ)の下位1byteのレジスタ |
Assembly Programming on x86-64 Linux (04)
レジスタと引数の関係は以下のようになっています。
引数 | レジスタ |
---|---|
第1引数 | RDI |
第2引数 | RSI |
第3引数 | RDX |
第4引数 | RCX |
第5引数 | R8 |
x86 calling conventions - Wikipedia
string系の関数の引数の順番の規則性を、アセンブリを読むことで理解できました。
movsb
最初は以下のようにint i = 0;みたいな感じで、インクリメントしながら、rdiに値を入れていく処理を想定していました。
.copy:
cmp BYTE [rsi + rax], 0
je .end
mov bl, BYTE[rsi + rax]
mov BYTE[rdi + rax], bl
inc rax
jmp .copy
movsbという命令を使えば、
while(*s)
*dst++ = *s++;
のような処理を1命令でかけるということがわかったので書換えました。