EDIT by yogev_ezra: Выделил "Реализация strlen на ассемблере" в отдельную тему.
Искал реализацию strlen на ассемблере, наткнулся на этот сайт:
http://www.int80h.org/ - Unix Assembly Language Programming
В примерах используется intel синтаксис.
Реализация strlen на ассемблере
http://www.manhunter.ru/assembler/403_n ... blere.html - там 3 варианта strlen в зависимости от того, что требуется производительность или малый размер кода.Insolor wrote:Искал реализацию strlen на ассемблере, наткнулся на этот сайт:
http://www.int80h.org/ - Unix Assembly Language Programming
В примерах используется intel синтаксис.
Эту статью вроде просматривал, но уже забыл про нее, поэтому полез в поиск. Для моих целей достаточно будет и первого варианта.Heavyiron wrote:http://www.manhunter.ru/assembler/403_n ... blere.html - там 3 варианта strlen в зависимости от того, что требуется производительность или малый размер кода.Insolor wrote:Искал реализацию strlen на ассемблере, наткнулся на этот сайт:
http://www.int80h.org/ - Unix Assembly Language Programming
В примерах используется intel синтаксис.
Во втором варианте можно дальше пойти:Heavyiron wrote:http://www.manhunter.ru/assembler/403_n ... blere.html - там 3 варианта strlen в зависимости от того, что требуется производительность или малый размер кода.
Spoiler:
Code: Select all
cmp byte [eax+3], 0
; ..............................
cmp byte [eax+255], 0
Первый вариант — наверное, первое, что приходит в голову
Я примерно так же сделал в kernel32, которая используется в PELoad.
lstrlenA, lstrlenW:
Spoiler:
Code: Select all
;**********************************************************************************
lstrlenA: ;////////////////////////////////////////////////////////////////////////
;**********************************************************************************
%define lpString [esp + 4 +1*4] ; null-terminated string to be checked
push edi
mov edi, lpString
xor ecx, ecx
dec ecx
xor al, al
repne scasb
not ecx
dec ecx
mov eax, ecx
pop edi
ret 4
%undef lpString
align 16
;**********************************************************************************
lstrlenW: ;////////////////////////////////////////////////////////////////////////
;**********************************************************************************
%define lpString [esp + 4 +1*4] ; null-terminated string to be checked
push edi
mov edi, lpString
xor ecx, ecx
dec ecx
xor ax, ax
repne scasw
not ecx
dec ecx
mov eax, ecx
pop edi
ret 4
%undef lpString
Но там не всё так хорошо, как могло быть.
Например lstrcatA.
У меня:
Spoiler:
Code: Select all
;**********************************************************************************
lstrcatA: ;////////////////////////////////////////////////////////////////////////
;**********************************************************************************
%define lpString1 [esp + 4 +2*4] ; first null-terminated string
%define lpString2 [esp + 8 +2*4] ; null-terminated string to be added
push esi
push edi
mov esi, lpString2
xor ecx, ecx
xor eax, eax
mov edi, esi
dec ecx
repne scasb
mov edx, ecx
mov edi, lpString1
repne scasb
dec edi
not edx
mov eax, lpString1
mov ecx, edx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
pop edi
pop esi
ret 8
%undef lpString1
%undef lpString2
Spoiler:
Code: Select all
lstrcatA proc uses esi edi string1:ptr byte,string2:ptr byte
xor eax,eax
mov ecx,-1
mov edi,string2
repne scasb
push ecx
mov edi,string1
repne scasb
dec edi
pop ecx
not ecx
mov esi,string2
shr ecx,1
rep movsw
adc ecx,ecx
rep movsb
mov eax,string1
ret
lstrcatA endp
Я у mike.dld в тинипаде наткнулся на 3-й вариант и он оказался на 4 байта короче и совсем чуть-чуть быстрее, чем первый:
На нем и остановился для своих целей.
Code: Select all
proc _lstrlen lpStr:DWORD
push ebx
mov ebx,[lpStr]
xor eax,eax
@@: cmp byte[ebx+eax],0
je @f
inc eax
jmp @b
@@: pop ebx
ret
endp
Heavyiron, ещё 3 подобных варианта:
Spoiler:
Code: Select all
; ------------------------------------
strlen1:
mov ecx, [lpStr]
mov eax, ecx
.next:
cmp [eax], byte 0
je .exit
inc eax
jmp .next
.exit:
sub eax, ecx
ret 4
; ------------------------------------
strlen2:
mov eax, [lpStr]
.next:
cmp [eax], byte 0
je .exit
inc eax
jmp .next
.exit:
sub eax, [lpStr]
ret 4
; ------------------------------------
strlen3:
mov eax, [lpStr]
dec eax
.next:
inc eax
cmp [eax], byte 0
jne .next
sub eax, [lpStr]
ret 4
; ------------------------------------
Последний крут (позволяет избавиться от push/pop, потому чуть быстрее и по размеру еще на 3 байта короче). А если заведомо известно, что длина строки ненулевая, можно убрать dec eax - еще минус 1 байт.
Красота!
Code: Select all
proc _lstrlen lpStr:DWORD
mov eax, [lpStr]
@@:
inc eax
cmp byte [eax], 0
jne @b
sub eax, [lpStr]
ret
endp
Выделил "Реализация strlen на ассемблере" в отдельную тему.
Ещё 1 вариант от 0CodErr:
Ещё 1 вариант от 0CodErr:
Code: Select all
strlen:
mov eax, [src]
.next:
cmp [eax], byte 1 ; IF byte[eax] = 0 THEN carry = 1
inc eax ; after "inc" carry not affected
jnc .next ; IF carry = 0 THEN next
sbb eax, [src] ; eax = eax - [src] - carry ; we here IF carry = 1
Who is online
Users browsing this forum: No registered users and 0 guests