将strlen从C重写为Assembly的问题

时间:2014-12-01 14:24:59

标签: assembly x86 strlen

你能帮助我吗?我必须将strlen函数从C重写为汇编语言。输入字符串以" 0h"结束。输出长度没有char" 0"。输入始终以" 0h"结束。 我有类似的东西,但它不起作用:

[segment .data use32] 

; ******************************************************************

str:          resb 50
str1:         resb 50
str2:         resb 50
aTmpWord:     dw 0   
aTmpDWord:    dd 0  
strlen:
push EBP
mov EBP, ESP
mov AL, 0h
mov EDI, dword [EBP + 8]
mov EBX, 0

vypocet_str:
cld
repne scasb
je koniec_str
inc EBX
mov EDI, [EDI + EBX]
jmp vypocet_str

koniec_str:
mov EAX, EBX
mov ESP, EBP 
pop EBP
ret
;************
prologue
push dword [str]
call strlen
call WriteNewLine
call WriteInt32
epilogue

1 个答案:

答案 0 :(得分:1)

您的代码中存在多个错误

1)strlen正式宣布为size_t strlen(const char *s);。参数是指向字符串的指针。使用push dword [str],您不会传递指针,而是传递字符串的前4个字节。将其更改为push str。 NASM(与MASM不同)然后计算str的地址。

2)cdecl调用约定确定参数在堆栈上传递,调用者必须清除堆栈。你正确推动了争论,但没有清除堆栈。在add esp, 4之后添加call strlen

3)repne需要初始化ECX。这是重复的最大计数。

4)repne是循环的指令。您不需要额外的循环(jmp vypocet_str)。当ECX> 0时,它重复以下指令,并且指令不会告诉"等于" (零标志设置)。因此,ECX可用于确定重新运行的计数 - 稍作调整。

TL; DR:这是你的美丽作业:

%include 'rw32.inc'     ; http://www.fit.vutbr.cz/~iklubal/IAS/

[segment .data use32]

    str: db "hello world", 0

[segment .code use32]

    strlen:
        push ebp
        mov ebp, esp
        mov al, 0
        mov edi, dword [EBP + 8]
        mov ecx, -1
        repne scasb
        neg ecx
        sub ecx, 2
        mov eax, ecx
        mov esp, ebp
        pop ebp
        ret

    prologue
    push str
    call strlen
    add esp, 4
    call WriteNewLine
    call WriteInt32
    epilogue