暇だったので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
ただしいですな