Сборка x86-32 и некоторые c функции - PullRequest
0 голосов
/ 26 ноября 2018

Я никогда не изучаю язык Си, поэтому меня это смущает.Я просто хотел бы знать, правильно ли я это сделал или где мне нужно улучшить.Для этого кода я использовал 32-битную сборку x86.Спасибо

Это то, что я должен был сделать: написать процедуру с подписью

char *strchar(char *s1, char c1)

, которая возвращает указатель на первое вхождение символа c1 в строке s1 или, если нетнайдено, возвращает ноль.

Вот что я получил:

strchar   (char*, char):  
push      ebp
mov       ebp,        esp
mov       dword       ptr     [ebp-24], edi
mov       EAX ,       esi
mov       BYTE PTR            [ebp-28], al

.L5:
mov       EAX ,       dword   ptr  [ebp-24]
movzx     EAX ,       byte ptr  [ EAX ]
test      AL, AL
je .L2
mov      EAX , dword PTR [ebp-24]
movzx   EAX , BYTE PTR [ EAX ]
cmp            BYTE PTR  [ebp-28], al
jne .L3
mov eax,      dword PTR [ebp-24]
jmp .L6

.L3:
add dword PTR [ebp-24], 1
jmp .L5
.L2:
LEA eax, [ebp-9]
MOV  DWORD PTR [EBP-8], eax
MOV  EAX, DWORD PTR [ebp-8]

.L6:    
POP EBP
RET

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Вот один с заголовком стека

[global strchar]
strchar:
            push    ebp
            mov     ebp, esp
            mov     dl, byte [ebp + 12]
            mov     ecx, dword [ebp + 8]
            xor     eax, eax
.loop:      mov     al, [ecx]
            or      al, al
            jz      .exit
            cmp     al, dl
            jz      .found
            add     ecx, 1
            jmp     .loop
.found:     mov     eax, ecx
.exit:
            leave
            ret

Вот один без заголовка стека

[global strchar]
strchar:
            mov     dl, byte [esp + 8]
            mov     ecx, dword [esp + 4]
            xor     eax, eax
.loop:      mov     al, [ecx]
            or      al, al
            jz      .exit
            cmp     al, dl
            jz      .found
            add     ecx, 1
            jmp     .loop
.found:     mov     eax, ecx
.exit:
            ret

Они используют соглашение о вызовах cdecl.Для 'stdcall' измените последний 'ret' на 'ret 8'.

0 голосов
/ 26 ноября 2018

Строки:

mov       dword       ptr     [ebp-24], edi
mov       EAX ,       esi
mov       BYTE PTR            [ebp-28], al

предполагают, что для этой функции был выделен кадр стека, что не соответствует действительности;Я думаю, у вас должно быть что-то вроде:

sub esp, 32

после

mov   ebp,esp

Кроме того, три строки после L2 кажутся запутанными.Единственный способ добраться до L2 - это обнаружение в строке байта nil (0), после чего код должен возвращать указатель NULL.Путь выхода в коде (L6) оставляет eax в покое, поэтому все, что нужно, это:

L2:
   mov eax, 0

Это может упростить отладку, если поддерживать псевдоним в актуальном состоянии;Итак:

L2:
   mov eax, 0
   mov [ebp-24], eax

Кроме того, соглашение о вызовах, используемое здесь, немного странно: строка передается в edi, а символ в esi.Обычно в x86-32 они оба передаются в стек.Похоже, это мог быть код x86-64, преобразованный в x86-32 ....

Последнее замечание;этот код сборки выглядит как выход компилятора с отключенными оптимизациями.Зачастую генерация сборки с включенной оптимизацией создает более понятный код.Этот код, например, мог бы быть написан гораздо более кратко, как показано ниже, даже не переходя в странные операции Intel:

strchar:
 mov edx, esi
 mov eax, edi
L:
 mov dh, [eax]
 test dh, dh
 jz   null
 cmp dh, dl
 je done
 inc eax
 jmp L
null:
 mov eax, 0
done:
 ret
...