我是 80386 汇编语言的新手。目前正在努力完成一项学校作业,要求用汇编语言编写一个将在 ac 程序中调用的函数。
extern int count(char *string, char c);
我想我知道应该如何做到这一点,但仍在努力选择正确的指令(指令以“b”、“w”或“l”结尾),也许还有“正确”的寄存器,我知道有一些为某些目的而保留的。
.text
.global count
count:
pushl %ebp # set up stack frame
movl %esp,%ebp # save %esp in %ebp
subl $12, %esp # automatic variables
movl $0, %eax # initialize %eax to 0
movl 8(%ebp), %esi # pointer to s
movb 12(%ebp), %bh # pointer to c
check:
movb (%esi), %bl # move the first char in s to %bl
cmp 0, %bl # if the char is \0
je done # job is done
cmp %bh, %bl # else compare the char to %bh
je found1 # if match increase the counter
incb %bl # else move to next char
jmp check
found1:
addl $1, %eax # found a match
incb %bl
jmp check # go back to the beginning of check
done:
movl %ebp, %esp # restore %esp from %ebp
popl %ebp # restore %ebp
ret
.end
Run Code Online (Sandbox Code Playgroud)
我对这个程序的理解是它应该将两个值(字符串和字符)的地址存储到两个寄存器中。然后逐个字符访问字符串,并将其与另一个寄存器中存储的字符进行比较。如果找到匹配,则增加 %eax 中的返回值,否则转到字符串中的下一个字符,直到\0
到达末尾。
任何帮助将不胜感激。
我认为没有真正的理由保存%esp
到%ebp
或从中减去%esp
。你确实需要保存%esi
。我认为a、b、c 和 d 寄存器可以安全地丢失,但如果没有(自从我使用汇编以来已经有一段时间了),您%ebx
也需要保存。
(更新:正如 @NateEldredge 指出的那样,%ebx
必须保留 - 我忘记更新堆栈指针。是的,它已经太长了)。
count:
pushl %esi # save %esi as we use it
pushl %ebx
# "In assembly language, all the labels and numeric constants used
# as immediate operands (i.e. not in an address calculation like
# 3(%eax,%ebx,8)) are always prefixed by a dollar sign."
# https://flint.cs.yale.edu/cs421/papers/x86-asm/asm.html
movl 12(%esp), %esi # pointer to s
movb 16(%esp), %bh # char
# I think it's more common "xor %eax, %eax"
movl $0, %eax # initialize %eax to 0
check:
movb (%esi), %bl # move the current char in s to %bl
cmp $0, %bl # if the char is \0
je done # job is done
cmp %bh, %bl # else compare the char to %bh
je found1 # if match increase the counter
# We must increase the pointer to the character, not %bl
incl %esi # else move to next char
jmp check
found1:
addl $1, %eax # found a match
# incb %bl
incl %esi # move to next char
jmp check # go back to the beginning of check
done:
popl %ebx
popl %esi # restore %esi
ret
.end
Run Code Online (Sandbox Code Playgroud)
您还可以反转测试以保存一些说明:
cmp %bh, %bl # else compare the char to %bh
jne notfound # if not match, skip incrementing
addl $1, %eax # found a match
notfound:
incl %esi # move to next char
jmp check
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
337 次 |
最近记录: |