3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

strcmp をx64アセンブラで実装してみる

Posted at

暇だったのでx64のアセンブラに手を出してみました。
普段x64を使っておいて知らないというのは癇に障るので。

nasmを使用しました。

strcmp.asm
bits 64
section .text
global strcmp

strcmp:
	enter 0, 0				;スタックフレーム作成
	mov [rbp + 16], rdi		;rdiを[rbp + 16]に保存
	mov [rbp + 24], rsi		;rsiを[rbp + 24]に保存
	cmp rcx, rdx			;引数が等しいなら
	je .eqend				;当然等しいので.eqendに飛ぶ

	mov rsi, rcx			;rsiにrcxを代入
	mov rdi, rdx			;rdiにrdxを代入
	cld						;rflagsのdfをクリアする
.ifeq:						;ループの始まりラベル
	mov al, [rsi]			;byte [rsi]をalに代入
	test al, [rdi]			;alとbyte [rdi]をand演算
	jz .sd					;片方でも次の文字がNUL文字なら.sdに飛ぶ
	cmpsb					;byte [rdi]とbyte [rsi]を比較してフラグを立ててrdiとrsiをインクリメントする
	je .ifeq				;もし比較結果が等しいならループの先頭へ戻る
	dec rsi					;違うならrsiと
	dec rdi					;rdiをデクリメントする
.sd:						;戻り値を作成するラベル
	mov al, [rsi]			;byte [rdi]をalに代入
	sub al, [rdi]			;alからbyte [rdi]を引いてalに代入
	movsx rax, al			;alを符号拡張してraxに代入
	jmp .end				;終了ラベルに飛ぶ

.eqend:						;rax(戻り値)をゼロにするラベル
	xor rax, rax			;raxをゼロにする
.end:						;終了ラベル
	mov rdi, [rbp + 16]		;rdiを復元
	mov rsi, [rbp + 24]		;rsiを復元
	leave					;スタックフレームを開放
	ret						;リターンする

#Windowsで使ってみる(VC)

test.cpp
#include <Windows.h>
#include <stdio.h>
#include <string.h>

const unsigned char asms[] = { 	//上のアセンブル結果を入れた配列
	0xC8, 0x00, 0x00, 0x00,
	0x48, 0x89, 0x7D, 0x10,
	0x48, 0x89, 0x75, 0x18,
	0x48, 0x39, 0xD1,
	0x74, 0x20,
	0x48, 0x89, 0xCE,
	0x48, 0x89, 0xD7,
	0xFC,
	0x8A, 0x06,
	0x84, 0x07,
	0x74, 0x09,
	0xA6,
	0x74, 0xF7,
	0x48, 0xFF, 0xCE,
	0x48, 0xFF, 0xCF,
	0x8A, 0x06,
	0x2A, 0x07,
	0x48, 0x0F, 0xBE, 0xC0,
	0xEB, 0x03,
	0x48, 0x31, 0xC0,
	0x48, 0x8B, 0x7D, 0x10,
	0x48, 0x8B, 0x75, 0x18,
	0xC9,
	0xC3
};

int main() {
	DWORD oldProtect;
	VirtualProtect((LPVOID)asms, sizeof(asms), PAGE_EXECUTE, &oldProtect);	//配列を実行させるためにメモリの保護を変更

	decltype(strcmp) *mystrcmp = (decltype(strcmp) *)(void*)asms;	//オリジナルのstrcmpの関数ポインタを作成して、配列のアドレスを無理矢理代入

	printf("mystrcmp(\"string\", \"STRING\"): %d\n", mystrcmp("string", "STRING"));	//"string"と"STRING"
	printf("mystrcmp(\"string\", \"string\"): %d\n", mystrcmp("string", "string"));	//"string"と"string"
	printf("mystrcmp(\"String\", \"string\"): %d\n", mystrcmp("String", "string"));	//"String"と"string"

	VirtualProtect((LPVOID)asms, sizeof(asms), oldProtect, &oldProtect);	//メモリの保護を元に戻す

	return 0;
}

めんどくさいので配列に機械語入れて実行させちゃいます。

result.txt
mystrcmp("string", "STRING"): 32
mystrcmp("string", "string"): 0
mystrcmp("String", "string"): -32

ただしいですな

3
3
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?