Bu başlık altında kendi oluşturmuş olduğum ya da faydalandığım 64 bit delphi assembly kodları paylaşacağım. Kodlar arasına mümkün mertebe yorum satırları ekleyeceğim.
Delphi'nin inttostr fonksiyonuna alternatif bir assembly fonksiyonu:
{
*Author: Hakan DİMDİK
*Last modified: 30/12/2020
*An alternatif function to inttostr
}
procedure intoansi(src:uint64; dst
ansichar);
asm
* *.noframe
* *//edx:eax bölünen, kalan dl
* *mov eax, ecx * //src'yi eax'e alıyoruz
* *mov r9, rdx * //string adresi
* *mov r10, 10 * *//constant 10
* *xor r8, r8 //basamak sayısı 0'dan başlıyor, çünkü indeks numarasıyla işlem yapacağız
@basamakLoop:
* *xor edx, edx *//dx sıfırlama
* *div r10d //eax'i 10'a bölüyoruz
* *add r8,1
* *cmp eax, 10
* *jae @basamakLoop
* *mov eax, ecx * //src'yi eax'e tekrar alıyoruz
* *cmp eax, r10d *//sayı ondan küçükse sona git
* *jb @Ret
@L:
* *xor edx, edx *//bölme işleminde kalan kısmı tekrar sıfırlıyoruz
* *div r10d //eax'i 10'a bölüyoruz
* *//kalanı ekledik
* *add dl, 48 * *//dl'den ascii karakteri elde ediyoruz
* *mov [r9+r8], dl
* *sub r8, 1
* *//bölüm 10'dan küçükse bitir
* *cmp eax, r10d
* *jb @Ret10
* *jmp @L;
@Ret10:
* *add al, 48
* *mov byte ptr [r9+r8], *al
* *ret
@Ret:
* *add al, 48 *//sayıya 48 eklenince ascii değerini alıyoruz
* *mov byte ptr [r9+r8], *al //indekse ascii değeri yaz
end;
Kullanımı:
procedure TestMy; *
var
*str:ansistring;
begin
* *SetLength(str,2);
* *intoansi(33,pansichar(str));
* *write(str);
* *Readln;
end;
Bu fonksiyon ansistring içindir.
Agner Fog'un hazırlamış olduğu asmlib kütüphanesinden*delphiye aktardığım StrLen fonksiyonu:
{
Agner Fog strlen function
https://github.com/tpn/agner/blob/master...rlen32.asm
}
function StrLen(const AStr: PAnsiChar): NativeUInt;
asm
* *.noframe
* *mov * * *rax, *rcx * * *//; string'in pointerini alıyoruz
* *mov * * *r8, * rcx * * *//; string'in pointerini kopyalıyoruz
* *//; rax = s, ecx = 32 bits of s
* *pxor * * xmm0, xmm0 * *//; xmm0 registerini sıfırlıyoruz
* *and * * *ecx, *0FH * * //; lower 4 bits indicate misalignment
* *and * * *rax, *-10H * *//; align pointer by 16
* *movdqa * xmm1, [rax] * //; read from nearest precedingboundary
* *pcmpeqb *xmm1, xmm0 * *//; compare 16 bytes with zero
* *pmovmskb edx, *xmm1 * *//; get one bit for each byte result
* *shr * * *edx, *cl * * *// * * * *; shift out false bits
* *shl * * *edx, *cl * * *// * * * *; shift back again
* *bsf * * *edx, *edx * * // * * * *; find first 1-bit
* *jnz * * *@L2 * * * * * *// * * * *; found
* *//; Main loop, search 16 bytes at a time
@L1: add * * rax, *10H * * // * * * *; increment pointer by 16
* *movdqa * xmm1, [rax] * // * * * *; read 16 bytes aligned
* *pcmpeqb *xmm1, xmm0 * *// * * * *; compare 16 bytes with zero
* *pmovmskb edx, *xmm1 * *// * * * *; get one bit for each byte result
* *bsf * * *edx, *edx * * // * * * *; find first 1-bit
* *//; (moving the bsf out of the loop and using test here would be faster for long strings on old processors,
* *//; *but we are assuming that most strings are short, and newer processors have higher priority)
* *jz * * * @L1
@L2: * * //; Zero-byte found. Compute string length
* *sub * * *rax, *r8 * // * * *; subtract start address
* *add * * *rax, *rdx * * * // * * *; add byte index
* *ret
end;
Standard length fonksiyonuna göre oldukça hızlıdır.
Delphi'nin inttostr fonksiyonuna alternatif bir assembly fonksiyonu:
{
*Author: Hakan DİMDİK
*Last modified: 30/12/2020
*An alternatif function to inttostr
}
procedure intoansi(src:uint64; dst
asm
* *.noframe
* *//edx:eax bölünen, kalan dl
* *mov eax, ecx * //src'yi eax'e alıyoruz
* *mov r9, rdx * //string adresi
* *mov r10, 10 * *//constant 10
* *xor r8, r8 //basamak sayısı 0'dan başlıyor, çünkü indeks numarasıyla işlem yapacağız
@basamakLoop:
* *xor edx, edx *//dx sıfırlama
* *div r10d //eax'i 10'a bölüyoruz
* *add r8,1
* *cmp eax, 10
* *jae @basamakLoop
* *mov eax, ecx * //src'yi eax'e tekrar alıyoruz
* *cmp eax, r10d *//sayı ondan küçükse sona git
* *jb @Ret
@L:
* *xor edx, edx *//bölme işleminde kalan kısmı tekrar sıfırlıyoruz
* *div r10d //eax'i 10'a bölüyoruz
* *//kalanı ekledik
* *add dl, 48 * *//dl'den ascii karakteri elde ediyoruz
* *mov [r9+r8], dl
* *sub r8, 1
* *//bölüm 10'dan küçükse bitir
* *cmp eax, r10d
* *jb @Ret10
* *jmp @L;
@Ret10:
* *add al, 48
* *mov byte ptr [r9+r8], *al
* *ret
@Ret:
* *add al, 48 *//sayıya 48 eklenince ascii değerini alıyoruz
* *mov byte ptr [r9+r8], *al //indekse ascii değeri yaz
end;
Kullanımı:
procedure TestMy; *
var
*str:ansistring;
begin
* *SetLength(str,2);
* *intoansi(33,pansichar(str));
* *write(str);
* *Readln;
end;
Bu fonksiyon ansistring içindir.
Agner Fog'un hazırlamış olduğu asmlib kütüphanesinden*delphiye aktardığım StrLen fonksiyonu:
{
Agner Fog strlen function
https://github.com/tpn/agner/blob/master...rlen32.asm
}
function StrLen(const AStr: PAnsiChar): NativeUInt;
asm
* *.noframe
* *mov * * *rax, *rcx * * *//; string'in pointerini alıyoruz
* *mov * * *r8, * rcx * * *//; string'in pointerini kopyalıyoruz
* *//; rax = s, ecx = 32 bits of s
* *pxor * * xmm0, xmm0 * *//; xmm0 registerini sıfırlıyoruz
* *and * * *ecx, *0FH * * //; lower 4 bits indicate misalignment
* *and * * *rax, *-10H * *//; align pointer by 16
* *movdqa * xmm1, [rax] * //; read from nearest precedingboundary
* *pcmpeqb *xmm1, xmm0 * *//; compare 16 bytes with zero
* *pmovmskb edx, *xmm1 * *//; get one bit for each byte result
* *shr * * *edx, *cl * * *// * * * *; shift out false bits
* *shl * * *edx, *cl * * *// * * * *; shift back again
* *bsf * * *edx, *edx * * // * * * *; find first 1-bit
* *jnz * * *@L2 * * * * * *// * * * *; found
* *//; Main loop, search 16 bytes at a time
@L1: add * * rax, *10H * * // * * * *; increment pointer by 16
* *movdqa * xmm1, [rax] * // * * * *; read 16 bytes aligned
* *pcmpeqb *xmm1, xmm0 * *// * * * *; compare 16 bytes with zero
* *pmovmskb edx, *xmm1 * *// * * * *; get one bit for each byte result
* *bsf * * *edx, *edx * * // * * * *; find first 1-bit
* *//; (moving the bsf out of the loop and using test here would be faster for long strings on old processors,
* *//; *but we are assuming that most strings are short, and newer processors have higher priority)
* *jz * * * @L1
@L2: * * //; Zero-byte found. Compute string length
* *sub * * *rax, *r8 * // * * *; subtract start address
* *add * * *rax, *rdx * * * // * * *; add byte index
* *ret
end;
Standard length fonksiyonuna göre oldukça hızlıdır.