gpt4 book ai didi

assembly - 减去两个字符

转载 作者:行者123 更新时间:2023-12-03 23:45:16 25 4
gpt4 key购买 nike

我刚开始用汇编编程,所以我是初学者。
为了练习,我试图用汇编(NASM Intel 语法)重写一个基本的 libc。
但我坚持使用 strcmp 函数:

;; Compare two C-style NUL-terminated strings
;; Inputs : ESI = address of s1, EDI = address of s2
;; Outputs : EAX = return an integer less than, equal to, or greater than zero if s1 is found, respectively, to be less than, to match, or be greater than s2
strcmp:
call strlen
mov ecx, eax ; ecx = length of the string in esi

repe cmpsb
sub esi, edi ; result = *esi - *edi

mov eax, esi

ret
对我来说,它应该像这样工作:
s1 db 'Hello World', 0
s2 db 'Hello Stack', 0
repe cmpsb说明, ESI应该等于 [s1 + 7]EDI[s2 + 7] .
所以我只需要做 EAX = 'W' - 'S' = 87 - 83 = 4
问题是,它不起作用。我认为问题是当我执行这条指令时:
sub esi, edi ; result = *esi - *edi
我不认为这意味着:减去 EDI 指向的字符和 ESI .
有没有人知道我如何做到这一点?

最佳答案

你的代码几乎是正确的。剩下三个问题:

  • 你不应该假设 strcmp保留 esi 的内容和 edi除非您明确指定它这样做。以后改很容易strcmp然后忘记要求,导致各种烦人的问题。
  • 而不是返回 *edi 之间的差异和 *esi ,你返回edi之间的差额和 esi .另外,如 cmpsb预付款 esiedi通过一,比较的最后一个字符位于 edi[-1]esi[-1] .
  • 您有一个逐一错误:strlen返回 NUL 字节之前的字符数,但您也需要比较 NUL 字节。否则,如果一个字符串是另一个字符串的前缀,您最终会发现两个字符串相等,因为您永远不会检查第二个字符串是否在第一个字符串结束时实际结束。

  • 为了解决第一个问题,我建议您保存和恢复 esiedi各地调用 strlen .最简单的方法是将它们压入堆栈:
        push esi             ; save ESI and EDI
    push edi
    call strlen ; compute the string length
    pop edi ; restore ESI and EDI
    pop esi
    第二个问题是通过从内存加载要比较的字符,计算差异,然后将结果存储到 eax 来解决的。 :
        movzx eax, byte [esi-1] ; load byte from ESI[-1] and zero extend into EAX
    movzx ecx, byte [edi-1] ; load byte from EDI[-1] and zero extend into ECX
    sub eax, ecx ; compute the difference
    这也通过立即使用正确的偏移量解决了第三个问题。请注意 movzx这里需要而不是稍微简单的
        mov   al, [esi-1]       ; load byte from ESI[-1] into AL
    sub al, [edi-1] ; subtract EDI[-1] from AL
    因为我们希望减法的结果正确地符号扩展为 eax .

    关于assembly - 减去两个字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63204722/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com